为了更清楚地理解诺言,我一直在阅读一些关于它的非常有趣的文章。我遇到了以下代码,这些代码非常适合顺序执行promise。但是我不明白它是如何工作的。
function doFirstThing(){
return new Promise(function(resolve,reject){
setTimeout(()=>{
resolve(1);
},1000)
})
}
function doSecondThing(res){
return new Promise(function(resolve,reject){
setTimeout(()=>{
resolve(res + 1);
},1000)
})
}
function doThirdThing(res){
return new Promise(function(resolve,reject){
setTimeout(()=>{
resolve(res + 2);
},1000)
})
}
promiseFactories = [doFirstThing, doSecondThing, doThirdThing];
function executeSequentially(promiseFactories) {
var result = Promise.resolve(); // this is the most problematic line
promiseFactories.forEach(function (promiseFactory) {
result = result.then(promiseFactory);// what is happening here ?
});
return result;
}
executeSequentially(promiseFactories)
我确实知道,承诺一旦创建便会立即执行。由于某种原因,我无法理解执行流程。特别是以下代码:
var result = Promise.resolve()//and empty promise is created.
如果有人可以帮助我理解在空promise的'then'方法内部调用promiseFactory方法是如何使其依次执行的,就像这样。还是因为forEach循环?
result = result.then(promiseFactory);
我尝试用“地图”功能替换“ forEach”,但仍然产生相同的结果。即按顺序执行的方法。 另外,该值如何从一个链接函数传递给另一个函数?
任何帮助或文章/博客都受到高度赞赏。
答案 0 :(得分:3)
如果您希望这样做,总是建议使用Promise.all
:
function doFirstThing() {
return new Promise(function(resolve, reject) {
setTimeout(() => {
resolve(1);
}, 1000)
})
}
function doSecondThing(res) {
return new Promise(function(resolve, reject) {
setTimeout(() => {
resolve(res + 1);
}, 1000)
})
}
function doThirdThing(res) {
return new Promise(function(resolve, reject) {
setTimeout(() => {
resolve(res + 2);
}, 1000)
})
}
let promiseFactories = [doFirstThing(2), doSecondThing(1), doThirdThing(3)];
Promise.all(promiseFactories)
.then(data => {
console.log("completed all promises", data);
})
要依次运行它:
function doFirstThing() {
return new Promise(function(resolve, reject) {
setTimeout(() => {
resolve(1);
}, 1000)
})
}
function doSecondThing(res) {
return new Promise(function(resolve, reject) {
setTimeout(() => {
resolve(res + 1);
}, 3000)
})
}
function doThirdThing(res) {
return new Promise(function(resolve, reject) {
setTimeout(() => {
resolve(res + 2);
}, 5000)
})
}
promiseFactories = [doFirstThing, doSecondThing, doThirdThing];
function executeSequentially(promiseFactories) {
promiseFactories.forEach(function(promiseFactory) {
promiseFactory(1).then((data) => {
console.log(data)
});
});
}
executeSequentially(promiseFactories);
答案 1 :(得分:3)
您可以将Promise成像为带有执行功能的盒子。只要创建了承诺,就开始执行。要获得结果值,您必须打开框。您可以使用then
:
Promise.resolve(5).then(result => console.log(result)); // prints 5
如果您要链接诺言,可以一一打开框:
Promise.resolve(5)
.then(result => Promise.resolve(result + 1))
.then(result => Promise.resolve(result * 2))
.then(result => console.log(result)); // prints 12
此链接使执行同步(一对一)。
如果您要异步执行几个承诺(不链接结果),则可以使用Promise.all
:
Promise.all([Promise.resolve(1), Promise.resolve(2), Promise.resolve(3)])
.then(result => console.log(result)); // prints [1,2,3]
在您的情况下:
Promise.all(promiseFactories).then(result => console.log(result));
使用诺言的另一种方法是await
:
(async ()=> {
var res1 = await Promise.resolve(5);
var res2 = await Promise.resolve(res1 + 1);
var res3 = await Promise.resolve(res2 * 2);
console.log(res3); // prints 12
})();
await
的工作方式与then
类似-它使异步执行变为同步。
在您的情况下:
async function executeSequentially(promiseFactories) {
for (const p of promiseFactories) {
const result = await p;
console.log(result);
}
}
注意: await
开箱即用地将值打包到Promise中:
var res1 = await 5; // same as await Promise.resolve(5)
答案 2 :(得分:1)
executeSequentially
方法一个接一个地返回所有Promises。它碰巧遍历了promiseFactory
,但是可以写成:
function executeSequentially(promiseFactories) {
return doFirstThing()
.then(() => doSecondThing())
.then(doThirdThing() );
}
是一样的。我们基本上是在返回诺言。
现在,我们要重申一系列承诺。
迭代时,我们需要使用then
将当前的Promise附加到前一个。但是forEach
不会在每次迭代中公开下一个Promise(或上一个)。但是,我们仍然需要它来保持Promises一对一的链接。因此,result
'hack':
function executeSequentially(promiseFactories) {
var result = Promise.resolve(); /*We need a thing that keeps yelling
the previous promise in every iteration, so we can keep chaining.
This 'result' var is that thing. This is keeping a Promise in every
iteration that resolves when all the previous promises resolve
sequentially. Since we don't have a Promise in the array
previous to the first one, we fabricate one out of 'thin air'
with Promise.resolve() */
promiseFactories.forEach(function (promiseFactory) {
result = result.then(promiseFactory); /* Here result is update
with a new Promise, with is the result of chaining `result`
with the current one. Since `result` already had all the previous ones,
at the end, `result` will be a Promise that depends upon all the
Promises resolution.*/
});
return result;
}
现在,还有一个语法怪癖可能使您感到困惑:
result = result.then(promiseFactory);
此行与以下内容几乎相同:
result = result.then(resolvedValue => promiseFactory(resolvedValue));
如果有人可以帮助我理解在空promise的'then'方法内部调用promiseFactory方法是如何使其依次执行的,就像这样。还是因为forEach循环?
首先,promiseFactory
在这里是一个非常糟糕的名字。该方法应更好地编写如下:
function executeSequentially(promises) {
var result = Promise.resolve(); // this is the most problematic line
promises.forEach(function (currentPromise) {
result = result.then(currentPromise);// what is happening here ?
});
return result;
}
所以:
如何在空promise的'then'方法内调用
currentPromise
方法以使其顺序执行?
它使顺序执行,因为当您通过then
将一个Promise附加到另一个时,它会顺序执行。是then
的事情,它与我们遍历Promises的事实完全无关。在迭代之外使用简单的Promises,其工作原理几乎相同:
Promise.resolve() // fake Promises that resolves instanly
.then(fetchUsersFromDatabase) // a function that returns a Promise and takes
// like 1 second. It won't be called until the first one resolves
.then(processUsersData) // another function that takes input from the first, and
// do a lot of complex and asynchronous computations with data from the previous promise.
// it won't be called until `fetchUsersFromDatabase()` resolves, that's what
// `then()` does.
.then(sendDataToClient); // another function that will never be called until
// `processUsersData()` resolves
答案 3 :(得分:1)
如果我们布置了foreach循环,它将看起来如下所示
function doFirstThing(){
return new Promise(function(resolve,reject){
setTimeout(()=>{
console.log(1);
resolve(1);
},1000)
})
}
function doSecondThing(res){
return new Promise(function(resolve,reject){
setTimeout(()=>{
console.log(2);
resolve(res + 1);
},2000)
})
}
function doThirdThing(res){
return new Promise(function(resolve,reject){
setTimeout(()=>{
console.log(3);
resolve(res + 2);
},3000)
})
}
Promise.resolve()
.then(doFirstThing())
.then(doSecondThing())
.then(doThirdThing());
我确实知道,承诺一旦创建便会立即执行。由于某种原因,我无法理解执行流程。特别是下面这行:
var result = Promise.resolve()//and empty promise is created.
这仅仅是为了掌握承诺链的起点。这是一个已经解决的承诺。为了更好地理解它,您可以使用您的一个承诺来获得如下所示的承诺链。
let promiseFactories= [doSecondThing, doThirdThing];
let result = doFirstThing();
promiseFactories.forEach(function (promiseFactory) {
result = result.then(promiseFactory);
});
这也将起作用。