诺言链序
Promise chain order
我使用下面的代码,有些东西让我有点困惑
如果我输入 1000 毫秒的超时时间,我会看到 promise 以正确的顺序调用
但如果我将其更改为以下
This is step 3
This is step 2
This is step 1
我想这是因为当函数是 resolved
然后他继续 next function
我是对的吗?如果这是真的,我怎么能做这个链,当第一个完成时 then
他继续第二个等等但没有使用 promise hell :-)
https://jsfiddle.net/2yym400j/
var step1 = function(ms) {
return new Promise(function(resolve, reject) {
setTimeout(function() {
console.log("This is step 1");
resolve();
}, ms);
})
}
var step2 = function(ms) {
return new Promise(function(resolve, reject) {
setTimeout(function() {
console.log("This is step 2");
resolve();
}, ms);
})
};
var step3 = function(ms) {
return new Promise(function(resolve, reject) {
setTimeout(function() {
console.log("This is step 3");
resolve();
}, ms);
})
};
step1(500)
.then(step2(300))
.then(step3(200))
.catch(function(err) {
console.log(err);
});
只传递一个函数而不是步骤的结果。
step1(500)
.then(function() { return step2(300); })
.then(function() { return step3(200); })
.catch(function(err) {
console.log(err);
});
没有这个,你只是在调用每个步骤,而没有 "blocking" 上一步来解决。
Daniel White 的评论和回答是正确的,但我认为额外的解释可能会有所帮助。
您的原始代码违反了两条规则:
then
不能接受 Promise,但它可以接受 returns Promise 的函数。如果你传入函数以外的任何东西,它将被忽略,就像你传入 null
相反。
- 只要您调用
new Promise(someFunction)
,someFunction
就会异步执行,无需等待任何事情。这意味着您可以从 then
函数中调用 new Promise
,但如果您提前调用它,那么它不会有您期望的延迟行为。
鉴于每次调用 stepN
returns 都是一个新构造的承诺,我已经内联了所有同步发生的事情并重命名了结果 constructAndReturnPromiseN
和 constructedPromiseThatStepNReturns
.这使得您的原始代码看起来像这样,所以所有的承诺都会立即发生:
constructedPromise1ThatStep1Returns
.then(constructedPromise2ThatStep2Returns) // BAD: Don't pass promises into then.
.then(constructedPromise3ThatStep3Returns) // BAD: Don't pass promises into then.
.catch(function(err) {
console.log(err);
});
...Daniel White 的代码是这样做的:
constructedPromise1ThatStep1Returns
// GOOD: The then function returns a promise that is *constructed inside* the function.
.then(function() { return constructAndReturnPromise2(300); })
.then(function() { return constructAndReturnPromise3(200); })
.catch(function(err) {
console.log(err);
});
我知道您已经得到关于为什么您的原始代码不起作用的答案,但我想我会展示另一种方法来解决它,它比您正在做的更干。您可以创建一个 returns 函数的函数,然后您可以按照您使用的方式使用它,因为它 returns 一个稍后将被调用的函数,这正是 .then()
想要的。所以,你可以这样做:
function delay(t, msg) {
return function() {
return new Promise(function(resolve) {
setTimeout(function() {
console.log(msg);
resolve();
}, t);
});
}
}
delay(500, "This is step 1")()
.then(delay(300,"This is step 2"))
.then(delay(200, "This is step 3"))
.catch(function(err) {
console.log(err);
});
我使用下面的代码,有些东西让我有点困惑 如果我输入 1000 毫秒的超时时间,我会看到 promise 以正确的顺序调用 但如果我将其更改为以下
This is step 3
This is step 2
This is step 1
我想这是因为当函数是 resolved
然后他继续 next function
我是对的吗?如果这是真的,我怎么能做这个链,当第一个完成时 then
他继续第二个等等但没有使用 promise hell :-)
https://jsfiddle.net/2yym400j/
var step1 = function(ms) {
return new Promise(function(resolve, reject) {
setTimeout(function() {
console.log("This is step 1");
resolve();
}, ms);
})
}
var step2 = function(ms) {
return new Promise(function(resolve, reject) {
setTimeout(function() {
console.log("This is step 2");
resolve();
}, ms);
})
};
var step3 = function(ms) {
return new Promise(function(resolve, reject) {
setTimeout(function() {
console.log("This is step 3");
resolve();
}, ms);
})
};
step1(500)
.then(step2(300))
.then(step3(200))
.catch(function(err) {
console.log(err);
});
只传递一个函数而不是步骤的结果。
step1(500)
.then(function() { return step2(300); })
.then(function() { return step3(200); })
.catch(function(err) {
console.log(err);
});
没有这个,你只是在调用每个步骤,而没有 "blocking" 上一步来解决。
Daniel White 的评论和回答是正确的,但我认为额外的解释可能会有所帮助。
您的原始代码违反了两条规则:
then
不能接受 Promise,但它可以接受 returns Promise 的函数。如果你传入函数以外的任何东西,它将被忽略,就像你传入null
相反。- 只要您调用
new Promise(someFunction)
,someFunction
就会异步执行,无需等待任何事情。这意味着您可以从then
函数中调用new Promise
,但如果您提前调用它,那么它不会有您期望的延迟行为。
鉴于每次调用 stepN
returns 都是一个新构造的承诺,我已经内联了所有同步发生的事情并重命名了结果 constructAndReturnPromiseN
和 constructedPromiseThatStepNReturns
.这使得您的原始代码看起来像这样,所以所有的承诺都会立即发生:
constructedPromise1ThatStep1Returns
.then(constructedPromise2ThatStep2Returns) // BAD: Don't pass promises into then.
.then(constructedPromise3ThatStep3Returns) // BAD: Don't pass promises into then.
.catch(function(err) {
console.log(err);
});
...Daniel White 的代码是这样做的:
constructedPromise1ThatStep1Returns
// GOOD: The then function returns a promise that is *constructed inside* the function.
.then(function() { return constructAndReturnPromise2(300); })
.then(function() { return constructAndReturnPromise3(200); })
.catch(function(err) {
console.log(err);
});
我知道您已经得到关于为什么您的原始代码不起作用的答案,但我想我会展示另一种方法来解决它,它比您正在做的更干。您可以创建一个 returns 函数的函数,然后您可以按照您使用的方式使用它,因为它 returns 一个稍后将被调用的函数,这正是 .then()
想要的。所以,你可以这样做:
function delay(t, msg) {
return function() {
return new Promise(function(resolve) {
setTimeout(function() {
console.log(msg);
resolve();
}, t);
});
}
}
delay(500, "This is step 1")()
.then(delay(300,"This is step 2"))
.then(delay(200, "This is step 3"))
.catch(function(err) {
console.log(err);
});