简体   繁体   English

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

[英]How to chain array of promises / functions with arguments using .reduce() in javascript

I'm looking to loop through an array of functions that return a promise, using reduce(). 我正在寻找使用reduce()遍历返回承诺的函数数组。 The goal is to chain them so they wait for the current iteration to be finished before starting the new one. 目标是将它们链接起来,以便它们在开始新迭代之前等待当前迭代完成。

This is especially confusing to me since I need to pass on the array index and another argument. 这让我特别困惑,因为我需要传递数组索引和另一个参数。

I know there's a few examples here and on google of that, but all of them are explained too abstractly for me and I can't understand them the way they are explained. 我知道在这里和谷歌上有一些例子,但是对我来说所有的例子都太抽象了,我无法理解它们的解释方式。

Here's my code (which is now working after edits): 这是我的代码(编辑后现在可以使用):

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
        });
})

Below is the function that is in each array of arrayOfFunctions. 下面是arrayOfFunctions的每个数组中的函数。 It gets passed to it using posts.map() in the above code. 它在上面的代码中使用posts.map()传递给它。 I think using .map() does it correctly. 我认为使用.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()
            })
        })
    })
}

This question is pretty hard to follow and the code appears to contain a number of mistakes so it's hard to figure out from that. 这个问题很难理解,而且代码似乎包含许多错误,因此很难从中找出来。

But, if I go back to your brief description, it sounds like may you want to execute an array of functions (that each return a promise) in sequence, waiting for one to finish before starting the next and you seem to want to use .reduce() to do that . 但是,如果我回到您的简要说明中,听起来您可能想要按顺序执行一系列函数(每个函数都返回一个Promise),等待一个函数完成再开始下一个函数,而您似乎想使用.reduce()来做到这一点 If that's the case, then you can do this: 如果是这样,则可以执行以下操作:

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
});

This code passes the resolved result of the previous promise to the next function in the array. 此代码将前一个诺言的解析结果传递给数组中的下一个函数。 You can obviously adapt that however you want. 您显然可以根据需要进行调整。 The resolved result of a .reduce() chain like this is the resolved result of the last promise. 像这样的.reduce()链的解析结果是最后一个promise的解析结果。 If you want to accumulate a result from all the operations, then one would typically either pass an object to each function where the resolved result is added to that object each time or create a side variable (like an array) where you accumulate results. 如果要累积所有操作的结果,则通常可以将一个对象传递给每个函数,每次将解析结果添加到该函数,或者创建一个边变量(如数组)来累积结果。

To answer your further questions: 要回答您的其他问题:

what is Promise.resolve() 什么是Promise.resolve()

That, by itself, creates a resolved promise. 这本身就创造了一个坚定的承诺。 We are using .reduce() to create a chain of promises as in x.then().then().then().then() . 我们正在使用.reduce()来创建诺言链,如x.then().then().then().then() To do that, we need a promise to start off the chain. 为此,我们需要一个从链上开始的承诺。 We use Promise.resolve() to initiate the chain. 我们使用Promise.resolve()来启动链。 So, it's essentially Promise.resolve().then().then().then() where inside each .then() handler, we execute the next function in the array and return its promise (thus adding it to the chain). 因此,本质上是Promise.resolve().then().then().then() ,其中在每个.then()处理函数中,我们执行数组中的下一个函数并返回其promise(因此将其添加到链中) 。

what is val ? 什么是val

val is the resolved value of the previous promise in the chain. val是链中前一个promise的解析值。 It will initially be undefined because the first promise is Promise.resolve() which doesn't have a resolved value. 最初将是undefined因为第一个承诺是Promise.resolve() ,它没有可解析的值。 After that, it will be whatever each function that returns a promise resolves to. 之后,将返回保证的每个函数解析为什么。 The .reduce() scheme you asked for, lends itself to passing the first result onto the second function, the second result onto the third function and so on. 您要求的.reduce()方案适合将第一个结果传递给第二个函数,将第二个结果传递给第三个函数,依此类推。

Where do I put my arguments (posts, i) needed for the function to work? 我在哪里放置函数正常运行所需的参数(帖子,i)?

return fn(val) is where your functions from the array of functions are called. return fn(val)是从函数数组中调用您的函数的地方。 If they need arguments, that's where you put them. 如果他们需要参数,那是您放置它们的地方。 Your question asked about an array of functions and did not describe what arguments you needed for those functions (I could not figure out your code well enough to understand that). 您的问题询问了一个函数数组,但没有描述这些函数所需的参数(我无法弄清楚您的代码足以理解这一点)。 If you want further help with that, then please describe in more detail exactly what arguments you need to pass to each function in the array of functions you said you started with. 如果您需要进一步的帮助,请更详细地描述您需要在开始使用的函数数组中传递给每个函数的参数。


OK, maybe I finally understand what you're trying to do. 好吧,也许我终于明白了您要做什么。 Here's my take on what you're trying to do. 这是我对您要尝试做的事情的看法。

  1. You want to call getAllPostsInfo() to get a list of posts. 您要调用getAllPostsInfo()以获取帖子列表。
  2. You then want to call printInfoMsg(posts) 然后,您想调用printInfoMsg(posts)
  3. You then want to call findAndInsertLinksToPosts() and then findAndInsertImgsIntoPostsContentandThunbnail() on each one of those posts. 那么你要调用findAndInsertLinksToPosts()然后findAndInsertImgsIntoPostsContentandThunbnail()对这些帖子中的每一个。
  4. And, you want these operations serialized so you operate on one post and only start on the next when the previous one is done (I'm not sure why you have that restriction) 而且,您希望将这些操作序列化,这样您就可以在一篇文章上进行操作,并且仅在完成前一篇文章时才在下一篇文章上开始(我不确定为什么会有这个限制)

If that's the case, then this is what I would suggest: 如果是这样,那么我会建议:

getAllPostsInfo(maxNumberOfPosts).then(posts => {
    // I'm assuming this is not asycnhronous
    printIntroMsg(posts);

    // now serially process each post
    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
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM