使用Promise构造函数转换数组中的每个元素并返回元素

时间:2018-02-13 16:53:46

标签: javascript arrays node.js geocoding es6-promise

我正在使用Geocodio,它是基于回调的地理编码。我有一个对象数组,每个对象都嵌套在其中。见下面的例子:

{
    id: 0, title: "Half off all pizzas", 
    details:"Carry out only, all-day", 
    days: ["Monday", "Tuesday"],
    restaurant: {
        name: "Papa John's", 
        addressOne: "2937 Greenville Ave", 
        city: "Dallas", 
        state: "TX", 
        zip: 75206
    } 
}

我目前正在映射对象数组,以将每个餐馆的地址传递到地理编码功能。我想再向该对象添加一个名为location的属性,该对象将包含地理编码的结果。但是,在将函数的结果传递到对象之前,将返回该元素。见下文:

generateCoordinates (req, res, next) {
    var newDeals = deals.map((cur, ind, arr) => {
        location = new Promise (function(resolve, reject) { 
            geocodio.get('geocode',  {q: `${cur.restaurant.addressOne}, 
                ${cur.restaurant.city}, ${cur.restaurant.state}, 
                ${cur.restaurant.zip}`}, function(err, response) {
                    if (err) {
                        reject(err)
                        throw err;
                    }
                    else {
                        var result = JSON.parse(response);
                        let obj = result.results[0].location;
                        // console.log(obj);
                        resolve(obj)
                    }
                }
            )}).then((obj) => {
                cur.location = obj;
                console.log(cur)
                return cur;
            })
        return cur;
        // console.log(newDeals)
    }) 
    res.status(200).send(newDeals)
},

我很有可能在这里滥用Promise构造函数。 .then中的console.log显示正确添加了location属性的每个元素,但响应和console.log(newDeals)将值显示为“Promise”。

如何设置数组中每个元素的location属性?

2 个答案:

答案 0 :(得分:1)

是的,您不应该在异步回调中执行任何操作,而是拨打resolvereject。特别是你不应该throw

return cur并不完全有效,因为它发生在承诺解决之前。您需要从map回调中返回承诺,然后使用Promise.all等待阵列中的所有承诺。当最终完成时,只有这样您才能发送响应。在发生错误时也不要忘记发送适当的回复。

generateCoordinates (req, res, next) {
    var newDeals = deals.map((cur, ind, arr) =>
        new Promise((resolve, reject) => {
            geocodio.get('geocode', {
                q: `${cur.restaurant.addressOne},
                    ${cur.restaurant.city}, ${cur.restaurant.state},
                    ${cur.restaurant.zip}`
            }, (err, response) => {
                if (err) reject(err);
                else resolve(response);
            });
        }).then(response => {
            var result = JSON.parse(response);
            let obj = result.results[0].location;
            cur.location = obj;
            console.log(cur)
            return cur;
        })
    );
    Promise.all(newDeals).then(results => {
        res.status(200).send(results);
    }, err => {
        res.status(500); // or whatever
        console.error(err);
    });
}

答案 1 :(得分:0)

所以你想要返回一个值数组?你几乎拥有它,但你需要等待Promises解决。像这样的东西:

generateCoordinates (req, res, next) {
    var newDeals = deals.map((cur, ind, arr) => {
        return new Promise (function(resolve, reject) { 
            geocodio.get('geocode',  {q: `${cur.restaurant.addressOne}, 
            ${cur.restaurant.city}, ${cur.restaurant.state}, 
            ${cur.restaurant.zip}`}, function(err, response) {
                if (err) {
                   return reject(err);
                }
                else {
                    var result = JSON.parse(response);
                    let obj = result.results[0].location;
                    // console.log(obj);
                    resolve(obj)
                }
            }
        )}).then((obj) => {
            cur.location = obj;
            console.log(cur)
            return cur;
        });

    //newDeals is an array of promises at this point
    Promise.all(newDeals).then(results => {
      //results here is a value resolved from your promise above
      return res.status(200).send(results)
    }).catch(er r=> {
    //handle errror
    });
},

我正在做的是使用map来创建一个promises数组。然后使用Promise.all等待承诺完成。无论您从then内的map区块返回的内容,最终都会以then Promise.all区块中的数组结尾。如果您拒绝任何承诺,它将自动在Promise.all

中捕获它们