Javascript 我应该如何构建承诺来处理多个相关异步任务?

Javascript 我应该如何构建承诺来处理多个相关异步任务?,javascript,asynchronous,promise,Javascript,Asynchronous,Promise,我读了一些如何重构代码以适应promise风格的示例,但它似乎需要其他promise库的帮助 我的问题是,我有多个异步任务,其中一些任务可能依赖于另一个调用的某些信息。 因此,我的代码如下所示: 假设我有一张图书馆的桌子。图书馆的桌子上有许多书。一本书有很多页。一页有许多照片 我还使用LoopBack为这些表创建实例 我有一个这种格式的库对象数组 { "location": "Hong Kong Island", "size": "25sq meter", "availa

我读了一些如何重构代码以适应promise风格的示例,但它似乎需要其他promise库的帮助

我的问题是,我有多个异步任务,其中一些任务可能依赖于另一个调用的某些信息。 因此,我的代码如下所示:

假设我有一张图书馆的桌子。图书馆的桌子上有许多书。一本书有很多页。一页有许多照片

我还使用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循环,我不知道如何展平调用。谁能提供一些见解?谢谢。

如果您使用的是
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-我想我现在很后悔在这里试图帮助你回答这个问题,因为你现在似乎已经把问题改成了除了它是什么以外的其他问题