[英]JavaScript Promises: Executing Promises Sequentially
為了更清楚地理解承諾,我一直在閱讀一些非常有趣的文章。 我遇到了以下代碼,它完美地用於順序執行promises。 但我無法理解它是如何工作的。
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)
我確實理解,promises會在創建后立即執行。 由於某種原因,我無法理解執行的流程。 特別是以下這一行:
var result = Promise.resolve()//and empty promise is created.
如果有人可以幫助我理解如何在空承諾的'then'方法中調用promiseFactory方法使它按順序執行,就像這樣。 或者是因為forEach循環?
result = result.then(promiseFactory);
我嘗試用'map'函數替換'forEach',但仍產生相同的結果。 即,順序執行的方法。 另外,值是如何從一個鏈式函數傳遞給另一個?
任何幫助或文章/博客都非常感謝。
如果你想要這樣的行為,總是建議使用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);
您可以將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(不鏈接結果),可以使用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));
如何使用promises的另一個選擇是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)
executeSequentially
方法一個接一個地返回所有Promises。 它碰巧迭代在promiseFactory
,但它可以寫成:
function executeSequentially(promiseFactories) {
return doFirstThing()
.then(() => doSecondThing())
.then(doThirdThing() );
}
它是一樣的。 我們基本上回歸了一個承諾。
但是,現在我們要迭代一系列承諾。
在迭代時,我們需要將當前的Promise附加到之前的then
。 但forEach
不會在每次迭代中暴露下一個Promise - 或前一個Promise。 然而,我們仍然需要它,以便逐一鏈接Promise。 因此, result
'黑客':
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));
如果有人可以幫助我理解如何在空承諾的'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;
}
所以:
如何在空承諾的'then'方法中調用
currentPromise
方法使其順序執行?
它使因為當你通過附加承諾到另一個是順序執行的then
,它依次執行。 是then
的事情,它是不是在所有相關的事實,我們遍歷承諾。 在迭代之外的普通Promise,它的工作方式幾乎相同:
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
如果我們布置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());
我確實理解,promises會在創建后立即執行。 由於某種原因,我無法理解執行的流程。 特別是以下行:
var result = Promise.resolve()//and empty promise is created.
這只是為了掌握承諾鏈的起點。 這是一個已經解決的承諾。 為了更好地理解它,您可以使用您的一個承諾來獲得承諾鏈,如下所示。
let promiseFactories= [doSecondThing, doThirdThing];
let result = doFirstThing();
promiseFactories.forEach(function (promiseFactory) {
result = result.then(promiseFactory);
});
這也行。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.