我读了一些示例,如何重构代码以适应承诺的风格,但似乎they可能需要其他承诺库的帮助。
我的问题是我有多个异步任务,其中一些可能依赖于另一个调用的某些信息。 所以我的代码看起来像这样:
我们说我有一张图书馆桌子。图书馆表有很多书。一本书有很多页面。一页有很多照片。
我也在使用LoopBack为这些表创建实例。
我有一个这种格式的库对象数组。
{
"location": "Hong Kong Island",
"size": "25sq meter",
"availableBooks" : [
{
"bookName": "Harry Potter",
"pages": 235,
"author": "J R Rowling"
"pages": [
{
"page": 1,
"content": "XXX",
"photos": [
{
"urlLink": "https://someLink",
"size": "360X250"
},
{
"urlLink": "https://google",
"size": "650X250"
}
]
}
,
{
"page": 2,
"content": "XXX"
}
]
},
{
"bookName": "Lord Of The Rings",
"pages": 335,
"author": "J. R. R. Tolkien"
}
]
}
对于伪代码,它看起来像这样。
for(something){
asyncCallA()
.then((A) => {
for(something){
asyncCallB(A)
.then((B) => {
for(something){
asyncCallC(B)
.then((C) => {
for(something){
asyncCallD(C)
}
})
}
})
}
})
}
对于常见情况,我了解如何使用promise来链接异步操作。但是在这种情况下异步调用相互依赖并且调用很多for循环,我不知道如何扁平化调用。任何人都可以提供一些见解吗?感谢。
答案 0 :(得分:3)
目前还不清楚你在问什么,但在for
循环中,你可以用链接代替嵌套。所以像这样:
asyncCallB(A)
.then((B) => {
asyncCallC(B)
.then((C) => {
asyncCallD(C)
})
})
可以替换为:
asyncCallB(A).then(B => {
return asyncCallC(B);
}).then(C => {
return asyncCallD(C);
});
如果你想要一个for
循环迭代等待前一个迭代完成(虽然你不会显示从一个循环迭代到下一个循环迭代的任何依赖),那么你必须要么将await
与主循环承诺一起使用(并且必须将父函数声明为async
),或者必须切换到手动迭代而不是for
循环的其他方式。
for(...) {
let loopResult = await asyncCallB(A).then(B => {
return asyncCallC(B);
}).then(C => {
return asyncCallD(C);
});
}
或者,很多时候,循环的各种迭代可以并行进行,但是你想知道它们何时完成:
let promises = [];
for(...) {
let p = asyncCallB(A).then(B => {
return asyncCallC(B);
}).then(C => {
return asyncCallD(C);
});
promises.push(p)
}
Promise.all(promises).then(results => {
// all promises in the loop done now
});
我还发现Bluebird promise library对于迭代非常有用,因为它提供的内容包括Promise.map()
,Promise.each()
,Promise.reduce()
和Promise.mapSeries()
你可以控制迭代(包括它的并行或串行以及你想要允许多少并发),并为你做更多的工作。
相关答案:
Using Promises with fs.readFile in a loop
Proper while() loop for bluebird promises (without recursion?)
How to synchronize a sequence of promises?
Javascript while loop where condition is a promise
bluebirdjs promises wrapped inside a for loop
How to chain promises in for loop in vanilla javascript
答案 1 :(得分:1)
如果您使用的是ES7
,则可以使用async / await。这是一个例子:
for(something){
let A = await asyncCallA();
for(something){
let B = await asyncCallB(A);
}
}
Node.JS 7.4.0及之后支持此项而没有任何实验性标志。