链式Q承诺序列不起作用

Chained Q Promise sequence wont work

本文关键字:不起作用 承诺 链式      更新时间:2023-09-26

Q PromiseNode.js应用程序中,我有这个代码,我想看到这个结果:

a
b
end

但是我看到了这个:

end
a
b

这是我的代码:

var a =  function(){
        return q.Promise(function(resolve, reject){
            resolve("a");
        });
    };
    var b =  function(){
        return q.Promise(function(resolve, reject){
            resolve("b");
        });
    };
    var c =  function(){
        return q.Promise(function(resolve, reject){
            resolve("c");
        });
    };
    var master =  q();
    master.then(function(){
        return a();
    })
    .then(function(res){
        console.error(res);
        return b();
    })
    .then(function(res){
        console.error(res);
            return c();
    });
    master.then(function(){
        console.error("end");
    });

如果我改变这个部分:

master.then(function(){
        return a();
    })

:

master = master.then(function(){
        return a();
    })

代码工作良好,但我不知道为什么?知道并理解这一点对我来说很重要。有人能给我解释一下吗?

你看到的是链接和分支之间的区别,它们是不同形式的承诺控制流。

当你这样做的时候:

master.then(function(){
    return a();
})

master.then(function(){
    console.error("end");
});

您已经将两个.then()处理程序连接到同一个承诺。这就是分支。当master()被解析时,这些.then()处理程序中的每一个都将被独立调用,并且每一个都成为它们自己独立的链(因此原始链被分支为两个链)。

链接就像:

master.then(function(){
    return a();
}).then(function(){
    console.error("end");
});

在链接的情况下,第二个.then()处理程序将不会被调用,直到a()返回的任何承诺也被解决,如果a()抛出或返回拒绝的承诺,第二个.then()处理程序将根本不会被调用。

在第一个示例中的分支情况中,第二个.then()处理程序在第一个.then()处理程序之后被调用,而不管a()返回什么。

当你这样做的时候:

master = master.then(function(){
    return a();
})

master.then(function(){
    console.error("end");
});

您正在手动链接它们,以便您有效地完成:

master.then(function(){
    return a();
}).then(function(){
    console.error("end");
});

记住,每次调用.then()返回一个新的承诺。链接,如:

a().then(b).then(c)

在链中的每一步都创建一个新的新承诺,并且在处理程序返回的任何内容也被解决之前,新承诺不会被解决。

所以,当你做:

master = master.then(function(){
    return a();
})

你正在抓取中间承诺(通过分配给master)并挂在它上面,这样你就可以把一些东西链到它上面。如果你只做:

master.then(function(){
    return a();
})

那么,从master.then()返回的promise已经完成,不能直接链接到。


链接与分支的进一步描述:

理解javascript承诺;栈和链接

promise.then.then和promise.then有区别吗?promise.then


下面是显示promise分支的代码片段:

function log(str) {
    var d = document.createElement("div");
    d.textContent = str;
    document.body.appendChild(d);
}
function setDelay(t, msg) {
    return function() {
        return delay(t, msg);
    }
}
function delay(t, msg) {
    // if only one string argument, default t to 500ms
    if (typeof t === "string" && typeof msg === "undefined") {
        msg = t;
        t = 500;
    }
    return new Promise(function(resolve) {
        setTimeout(function() {
            log(msg);
            resolve(msg);
        }, t);
    });
}
var x = Promise.resolve().then(setDelay("One"))
	.then(setDelay("Two"))
	.then(function() {
    	log("Three");
	});
x.then(setDelay(500, "Four"))
    .then(setDelay(500, "Five"))
    .then(setDelay(500, "Six"));
x.then(setDelay(50, "Seven"))
    .then(setDelay(50, "Eight"))
    .then(setDelay(50, "Nine"));
x.then(setDelay(10, "Ten"))
    .then(setDelay(10, "Eleven"));

1、2、3被连锁在一起,所有的分支都依赖于它们。然后,这条链分成三个独立的分支。

Ten, Eleven分支首先执行,因为它有10ms的计时器。

接下来是7,8,9分支,计时器为50ms。

然后,四,五,六分支以500毫秒的计时器最后执行

注意:我故意这样做,所以分支计时器不重叠,但这不是承诺强制的东西,这恰好是这里的情况,因为我选择的计时器值。所有三个分支都是独立运行的,如果它们的活动有重叠的时间,则可以交叉运行。