Javascript 我应该如何构建承诺来处理多个相关异步任务?
我读了一些如何重构代码以适应promise风格的示例,但它似乎需要其他promise库的帮助 我的问题是,我有多个异步任务,其中一些任务可能依赖于另一个调用的某些信息。 因此,我的代码如下所示: 假设我有一张图书馆的桌子。图书馆的桌子上有许多书。一本书有很多页。一页有许多照片 我还使用LoopBack为这些表创建实例 我有一个这种格式的库对象数组Javascript 我应该如何构建承诺来处理多个相关异步任务?,javascript,asynchronous,promise,Javascript,Asynchronous,Promise,我读了一些如何重构代码以适应promise风格的示例,但它似乎需要其他promise库的帮助 我的问题是,我有多个异步任务,其中一些任务可能依赖于另一个调用的某些信息。 因此,我的代码如下所示: 假设我有一张图书馆的桌子。图书馆的桌子上有许多书。一本书有很多页。一页有许多照片 我还使用LoopBack为这些表创建实例 我有一个这种格式的库对象数组 { "location": "Hong Kong Island", "size": "25sq meter", "availa
{
"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循环,我不知道如何展平调用。谁能提供一些见解?谢谢。如果您使用的是
ES7
,您可以使用async/await。以下是一个例子:
for(something){
let A = await asyncCallA();
for(something){
let B = await asyncCallB(A);
}
}
Node.JS 7.4.0及其后版本不支持任何实验性标志。如果您使用的是
ES7
,则可以使用async/await。以下是一个例子:
for(something){
let A = await asyncCallA();
for(something){
let B = await asyncCallB(A);
}
}
Node.JS 7.4.0及其后版本不支持任何实验性标志。不清楚您到底在问什么,但在
for
循环中,您可以用链接替换嵌套。比如说:
asyncCallB(A)
.then((B) => {
asyncCallC(B)
.then((C) => {
asyncCallD(C)
})
})
可替换为以下内容:
asyncCallB(A).then(B => {
return asyncCallC(B);
}).then(C => {
return asyncCallD(C);
});
如果希望一个for
循环迭代等待前一个循环迭代完成(尽管您没有显示从一个循环迭代到下一个循环迭代的任何依赖性,这是必需的),那么您必须使用wait
和主循环承诺(并且父函数必须声明为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
});
我还发现了非常有用的迭代方法,因为它有Promise.map()
,Promise.each()
,Promise.reduce()
和Promise.mapSeries()
等功能,可以让您对迭代进行一些控制(包括是并行还是串行,以及您希望允许多少并发)为你做更多的工作
有关答案:
不清楚您到底在问什么,但是在
for
循环中,您可以用链接替换嵌套。比如说:
asyncCallB(A)
.then((B) => {
asyncCallC(B)
.then((C) => {
asyncCallD(C)
})
})
可替换为以下内容:
asyncCallB(A).then(B => {
return asyncCallC(B);
}).then(C => {
return asyncCallD(C);
});
如果希望一个for
循环迭代等待前一个循环迭代完成(尽管您没有显示从一个循环迭代到下一个循环迭代的任何依赖性,这是必需的),那么您必须使用wait
和主循环承诺(并且父函数必须声明为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
});
我还发现了非常有用的迭代方法,因为它有Promise.map()
,Promise.each()
,Promise.reduce()
和Promise.mapSeries()
等功能,可以让您对迭代进行一些控制(包括是并行还是串行,以及您希望允许多少并发)为你做更多的工作
有关答案:
不确定问题代码的问题是什么?因为异步调用相互依赖,我不知道如何展平代码。如果我这样做,它会不会反对承诺的想法,因为承诺是为了压扁地狱?你说的“压扁”是什么意思?您实际使用的代码是什么?请看,当代码只是伪代码时,很难提供一个很好的答案。详细的答案需要真实的代码来显示您的真实问题。迭代一个包含书籍的表,其中包含具有图像的页面,只需要嵌套循环。除非您编写一些泛型函数来迭代任意嵌套数据结构的所有节点,否则没有更多的声明性方法来编写包含一系列嵌套循环的代码。如果这就是您的代码目标,那么这就是您编写的代码。就我个人而言,我可能会将它分解为一系列可恢复的函数,
iterateTables()
,iterateBooks()
,iteratePages()
,iterateAges()
等等,然后它看起来会更干净。不确定问题代码有什么问题?因为异步调用彼此依赖,我不知道如何将代码扁平化。如果我这样做,它会不会反对承诺的想法,因为承诺是为了压扁地狱?你说的“压扁”是什么意思?您实际使用的代码是什么?请看,当代码只是伪代码时,很难提供一个很好的答案。详细的答案需要真实的代码来显示您的真实问题。迭代一个包含书籍的表,其中包含具有图像的页面,只需要嵌套循环。除非您编写一些泛型函数来迭代任意嵌套数据结构的所有节点,否则没有更多的声明性方法来编写包含一系列嵌套循环的代码。如果这就是您的代码目标,那么这就是您编写的代码。就个人而言,我可能会将其分解为一系列可恢复的函数iterateTables()
,iterateBooks()
,iteratePages()
,iterateAges()
等等,然后它看起来会更干净。@kenkwok-我想我现在很后悔在这里试图帮助你回答这个问题,因为你现在似乎已经把问题改成了除了它是什么以外的其他问题