Promise.All - Promise 中的 Promise 未解决 [英] Promise.All - Promise Within Promise Not Being Resolved

查看:65
本文介绍了Promise.All - Promise 中的 Promise 未解决的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

您好,我正在继续学习 Promise,并且正在为如何正确使用 Promise.All 或在这种情况下是否应该使用它而苦苦挣扎.

Hello I am continuing to learn promises and am struggling with how to correctly use Promise.All or whether or not I should be using it in this situation.

我正在连接到一个数据源并将我的第一个承诺解析为一个数组.之后,我想获取这些结果,并使用另一个 Promise 循环遍历结果并向使用外部 API 调用的数组添加另一个值.

I am connecting to a data source and resolving my first promise to an array. After that I want to take those results and with another promise loop through the results and add another value to the array which is using an external API call.

经过研究,听起来我需要使用 Promise.All 以便在返回我的响应之前完成承诺,但我仍然在我添加到我的数组而不是预期值的值上获得挂起状态.同样,我只是在学习 node 和 promise,所以我的方法可能完全有缺陷,在这种情况下,我愿意接受任何关于更好的方法来完成我正在尝试完成的工作的建议.

After research it sounded like I needed to use Promise.All so that the promises would be completed before returning my response but I am still getting a status of pending on the value that I am adding to my array instead of the expected value. Again I am just learning node and promises so my approach might be completely flawed and in that case I am open to any suggestions on a better way to do what I am attempting to accomplish.

function GetSearches(req, res) { 

    var BingSearches = new Promise((resolve, reject) => {
        GetBingSearches().toArray((err, response)=>{
            resolve(response);
        });          
    }) /* get data from external data source example data: [{SearchTerm: "Boxing", id: '4c142f92-ba6d-46af-8dba-cb88ebabb94a', CreateDate: '2017-08-10T13:59:20.534-04:00'}] */


    var GetSearchesWithImageUrl = BingSearches.then((response,reject) =>{
        for(var i in response){
            response[i].Image = new Promise((resolve, reject) => { 
                Bing.images(response[i].SearchTerm, {
                count: 1
                }, (err,res,body) => {
                    const bingImageUrl = body.value[0].contentUrl;
                    console.log(bingImageUrl) // bing image url link
                    resolve(bingImageUrl);
                });
            });
        } // loop through array and add value

        return response;
    }).catch((err) => {
        console.log(err);
    })

    return Promise.all([BingSearches ,GetSearchesWithImageUrl ]).then(([BingSearches , GetSearchesWithImageUrl ]) => {
        console.log(GetSearchesWithImageUrl )
         /* my response is now [{SearchTerm: "Boxing", id: '4c142f92-ba6d-46af-8dba-cb88ebabb94a', CreateDate: '2017-08-10T13:59:20.534-04:00', Image: Promise { pending } }] */

        res.status(200).json(GetSearchesWithImageUrl )
    }).catch((err) => {
        console.log(err);
    })
}

我希望 Promise.All 会等待我所有的承诺完成,但我似乎不明白它是如何工作的.我愿意接受任何关于我做错了什么的建议/解释.

I was hoping that Promise.All would wait for all my promises to complete but I do not seem to understand how it works. I am open to any advice/explanation of what I am doing wrong.

谢谢!

推荐答案

这是我对这个问题最好的尝试:

Here's my best stab at this problem:

// Promisified search, resolves to response array
function getBingSearchesPromise() {
    return new Promise((resolve, reject) => {
        GetBingSearches().toArray((err, response) => {
            if (err) {
                reject(err);
            } else {
                resolve(response);
            }
        });          
    });
}

// get first image url for a search term, resolves to an image URL
function getBingImagePromise(term) {
    return new Promise((resolve, reject) => {
        Bing.images(term, {count: 1}, (err, res, body) => {
            if (err) {
                reject(err);
            } else {
                resolve(body.value[0].contentUrl);
            }
        });
    });
}


// no need to pass req or res into here
// returns promise, resolves to array of images URLs
function GetSearches() {
    return getBingSearchesPromise().then(searchResponses => {
        // get all images
        let promises = searchResponses.map(searchItem => {
            return getBingImagePromise(searchItem.SearchTerm);
        });
        return Promise.all(promises);
    })    
}

// then inside your request handler where you have req and res, you can do this
GetSearches().then(images => {
    res.json(images);
}).catch(err => {
    console.log(err);
    res.status(500).end();
});

因为您的代码相距甚远,并且没有包含您正在尝试执行的操作的文字描述,所以这是对您正在尝试完成的有根据的猜测.如果我的猜测有误,您可以从中学习并将其应用于您的实际问题,或者我可以删除我的答案.

Because your code was pretty far off and did not include a words description of what you are trying to do, this is an educated guess about you're trying to accomplish. If I got the objective wrong with my guess, you can either just learn from this and apply it to your actual problem or I can delete my answer.

变更摘要:

  1. 单独承诺异步操作,然后使用承诺构建所有逻辑(没有简单的回调).如果我们可以看到 GetBingSearches() 的代码,它可能会做得更好,它可能应该将一些参数传递给它,而不是硬连接来执行特定类型的搜索.

  1. Promisify async operations separately, then build all logic with promises (no plain callbacks). This could probably be done even better if we could see the code for GetBingSearches() which should probably have some arguments passed into it rather than be hard-wired to do a specific type of search.

获取搜索承诺并使用 .then() 等待它以获取结果数组.

Get the searches promise and wait for it with .then() to get an array of results.

在那个 .then() 处理程序中,使用 .map() 来获取每个图像 URL 并创建一个承诺数组.

In that .then() handler, use .map() to fetch each image URL and create an array of promises.

使用 Promise.all() 等待一系列 Promise.

Wait for that array of promises with Promise.all().

从这段代码中分离出reqres,因为只有最终响应需要使用res,这样你的代码就可以更有用,您只需从响应处理程序中调用此代码即可获得结果,而无需将 res 传递到其中.

Separate out req and res from this code because only the final response needs to use res so this way you code can be more usable and you can just call this code from the response handler and get the result without passing res into it.

为所有错误添加错误处理.将所有错误传播到链上.

Add error handling for all errors. Propagate all errors back up the chain.

切勿使用 for/in 迭代数组(它迭代对象的属性,而不仅仅是数组元素).如果您想要的结果是 1 对 1 数组,那么 .map() 非常适合.否则,在 ES6 中,使用 for/of 来迭代数组.

Never use for/in to iterate an array (it iterates properties of an object, not just array elements). If your desired result is a 1-to-1 array, then .map() is perfect for that. Otherwise, in ES6, use for/of to iterate an array.

这篇关于Promise.All - Promise 中的 Promise 未解决的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆