如何在 javascript 中使用 .reduce() 链接带有参数的 Promise/函数数组

JPB*_*JPB 1 javascript node.js promise

我正在寻找使用reduce() 循环遍历返回promise 的函数数组。目标是将它们链接起来,以便它们等待当前迭代完成后再开始新的迭代。

这对我来说尤其令人困惑,因为我需要传递数组索引和另一个参数。

我知道这里和谷歌上有一些例子,但所有这些对我来说都解释得太抽象了,我无法理解它们的解释方式。

这是我的代码(编辑后现在可以工作):

getAllPostsInfo(maxNumberOfPosts)

.then((posts) => {                                                                      
    printIntroMsg(posts)
    var arrayOfFunctions = posts.map( () => {
        return main
    })

    arrayOfFunctions.reduce((p, fn, i) => {
    return p.then( () => {

        // you may customize what you pass to the next function in the chain
        // and you may accumulate prior results in some other data structure here
        return fn(posts, i);
    });
    }, Promise.resolve() )
        .then(result => {
            // all done here
        }).catch(err => {
            // error here
        });
})
Run Code Online (Sandbox Code Playgroud)

下面是每个 arrayOfFunctions 数组中的函数。它是使用上面代码中的 posts.map() 传递给它的。我认为使用 .map() 可以正确执行。

function main(posts, i) {
    return new Promise( (resolve,reject) => {
        findAndInsertLinksToPosts(posts[i], posts,i)

        .then( () => {
            findAndinsertImgsIntoPostContentandThumbnail(posts[i],posts,i)

            .then( () => {
                console.log("FINISHED!")
                resolve()
            })
        })
    })
}
Run Code Online (Sandbox Code Playgroud)

jfr*_*d00 5

这个问题很难理解,并且代码似乎包含许多错误,因此很难从中找出答案。

但是,如果我回到您的简短描述,听起来您可能想按顺序执行一组函数(每个函数都返回一个承诺),等待一个函数完成后再开始下一个函数,并且您似乎想.reduce()使用去做。如果是这种情况,那么您可以这样做:

let arrayOfFunctions = [...];

arrayOfFunctions.reduce((p, fn, index) => {
    return p.then(val => {
        // you may customize what you pass to the next function in the chain
        // and you may accumulate prior results in some other data structure here
        return fn(val);
    });
}, Promise.resolve()).then(result => {
    // all done here
}).catch(err => {
    // error here
});
Run Code Online (Sandbox Code Playgroud)

此代码将前一个 Promise 的解析结果传递给数组中的下一个函数。显然,您可以根据需要进行调整。像这样的链的解析结果.reduce()是最后一个承诺的解析结果。如果您想累积所有操作的结果,那么通常要么将一个对象传递给每个函数,每次将解析的结果添加到该对象,要么创建一个辅助变量(如数组)来累积结果。

回答您的进一步问题:

什么是 Promise.resolve()

这本身就创造了一个坚定的承诺。我们正在使用.reduce()创建一个承诺链,如x.then().then().then().then(). 为此,我们需要一个启动链的承诺。我们用来Promise.resolve()启动链。因此,本质上是Promise.resolve().then().then().then()在每个处理程序内部.then(),我们执行数组中的下一个函数并返回其承诺(从而将其添加到链中)。

什么是val

val是链中前一个承诺的解析值。最初是undefined因为第一个承诺Promise.resolve()没有解决的价值。之后,它将是返回 Promise 的每个函数解析的结果。您要求的方案.reduce()适合将第一个结果传递到第二个函数,将第二个结果传递到第三个函数,依此类推。

我应该把函数运行所需的参数(posts,i)放在哪里?

return fn(val)是调用函数数组中的函数的地方。如果他们需要争论,那就是你把他们放在那里。您的问题询问了一系列函数,但没有描述这些函数所需的参数(我无法很好地理解您的代码以理解这一点)。如果您需要进一步的帮助,请更详细地描述您需要传递给您所说的开始的函数数组中的每个函数的参数。


好吧,也许我终于明白你想做什么了。这是我对你想做的事情的看法。

  1. 您想致电getAllPostsInfo()获取帖子列表。
  2. 然后你想打电话printInfoMsg(posts)
  3. 然后你想打电话findAndInsertLinksToPosts()findAndInsertImgsIntoPostsContentandThunbnail()这些帖子中的每一个。
  4. 而且,您希望这些操作被序列化,这样您就可以在一篇文章上进行操作,只有在上一篇文章完成后才开始下一篇文章(我不确定为什么有这个限制)

如果是这样的话,那么我的建议是:

getAllPostsInfo(maxNumberOfPosts).then(posts => {
    // I'm assuming this is not asycnhronous
    printIntroMsg(posts);
    
    // now serially process each post
    return posts.reduce((promise, post, i) => {
        return promise.then(() => {
            return findAndInsertLinksToPosts(post, posts, i).then(() => {
                return findAndInsertImgsIntoPostContentandThumnail(post, posts, i);
            });
        });
    }, Promise.resolve());
}).then(() => {
    // all done here
}).catch(err => {
    // error here
});
Run Code Online (Sandbox Code Playgroud)