javascript - Node.js 无法使用 Promise、Mongoose 和 GET 请求推送到全局数组

标签 javascript arrays json node.js mongoose

我无法将所需的结果推送到我在使用 Q Promise 库创建的同步函数中定义的数组。根据汽车品牌、用户位置的邮政编码和最大半径,此功能有 3 个任务:

  1. 查询我的经销商集合,以根据输入的特定制造商用户检索经销商 ID。
  2. 然后我定义一个数组:dealershipIDs。该数组将用于推送某些经销商 ID。然后,我迭代返回的经销商 json 列表,以检索经销商的各个 ID 名称及其邮政编码。我向 api 服务发出 GET 请求,以计算用户输入的位置与任务 1 中找到的每个经销商之间的距离。如果经销商与用户之间的距离小于输入的半径,则该经销商的 ID 名称将添加到数组中我想传递到步骤 3。我这样做不成功,因为我尝试传递的数组是空的,并且不包含 for 循环之外的 id 名称。
  3. 查询我的汽车集合中包含经销商 ID 列表的汽车。最后一步将在用户区域中呈现带有汽车结果的适当页面。

任务 2 是我的问题。我能够将正确的经销商 id 添加到我定义的数组中,但我无法将该数组传递给下一个 .then,因为该数组在 for 循环之外为空。

我已经被这个问题困扰好几天了,我已经尝试了一切。如果我可以更具体,请告诉我。

exports.getCarIndexPage = function(req, res) {
  var m = req.session.make; // User input
  var zipcode = req.session.zipcode; // User input
  var radius = req.session.radius; // User input
  req.session.valid = null; // Resets session variable

  Dealership.find({makes: m}).exec()
    .then(function (ids) {
        var dealershipIDs = []; /* Trying to add dealer ids to array */
        ids.forEach(function (id) {
            var id = ids[i];
            getDistanceWithAPI(zipcode, id.zip, function(distanceVal) {
                console.log("This is the distance: " + distanceVal.distance);
                if (distanceVal.distance <= radius) {
                    console.log("Adding " + id._id + " to array");
                    dealershipIDs.push(id._id); // Adding dealership's id to array
                    console.log("Size of dealership array: " + dealershipIDs.length);
                }   
                console.log("Inside for loop = Size of dealership array: " + dealershipIDs.length); /* Recognizes the array size! */
            })
        })
        console.log("Outside for loop = Size of dealership array: " + dealershipIDs.length); /* Does not recognize array size */
        return dealershipIDs; /* Return this array that contains the dealership ids */
    }).then(
        function (resultArray) {
            Car.find({dealership_id: { $in: resultArray }}).exec()
                .then(function (cars) {
                    console.log(cars);
                }),
                function (error) {
                    console.log("Could not iterate through through cars: " + error);
                }   
    }, function (error) {
        console.error("Error with the outer promises:", error);
    });
}

如何通过添加到 DealshipIDs 数组来使此函数起作用,以便我可以将其传递以用于查询我的汽车收藏?

以下函数是我的 HTTP 请求,它返回从 A 点到 B 点的距离的 JSON 对象,即(距离:1.664}

function getDistanceWithAPI(userInput, dealerZip, callback) {
https.get('https://www.zipcodeapi.com/rest/xApFwnm4tosuL2gX2UDQIGcknN2NIHyfhXVNlhRPFkjrmzpou2edJry7fAVXhtdz/distance.json/' 
        + userInput + '/' + dealerZip + '/mile', function(res) {
  var body = ''; // Will contain the final response

  res.on('data', function(data){
    body += data;
  });

  // After the response is completed, parse it and log it to the console
  res.on('end', function() {
    var parsed = JSON.parse(body);
    callback(parsed); // i.e. returns {distance : 1.664 } 
  });
})

// If any error has occured, log error to console
.on('error', function(e) {
  console.log("Got error: " + e.message);
});
}

这是我的日志:

Server running at http://localhost:3000/
Outside for loop = Size of dealership array: 0
[]
This is the distance: 1.664
Adding bmwofsf to array
Size of dealership array: 1
Inside for loop = Size of dealership array: 1
This is the distance: 13.685
Adding bmwofsanrafael to array
Size of dealership array: 2
Inside for loop = Size of dealership array: 2

最佳答案

我猜问题是因为在第二个任务中, getDistanceWithAPI 是一个异步函数。因此,第二个任务将在任何 getDistanceWithAPI 解析之前快速返回。让我尝试使用 preso 代码来解决下面的问题。它并不完美,因为它引入了全局数组,也许我们可以通过使用 Q.all 来改进它。

var dealershipIDs = []; /* put it outside, because the results in 2nd tasks is used to indicated the finished state.  */
Dealership.find({makes: m}).exec()
    .then(function (ids) {
        var promises = []
        for (var i = 0; i < ids.length; i++) {
            var id = ids[i];
            promises.push(getDistanceWithAPI(zipcode, id.zip, function(distanceVal) { // Returns promise
                console.log("This is the distance: " + distanceVal.distance);
                if (distanceVal.distance <= radius) {
                    console.log("Adding " + id._id + " to array");
                    dealershipIDs.push(id._id); // Adding dealership's id to array
                    console.log("Size of dealership array: " + dealershipIDs.length);
                }   
                console.log("Inside for loop = Size of dealership array: " + dealershipIDs.length); /* Recognizes the array size! */
            }));
        }
        console.log("Outside for loop = Size of dealership array: " + dealershipIDs.length); /* Does not recognize array size */
        return Q.all(promises); // resolve all promises and return;
    }).then(
        function () {
            var resultArray = dealershipIDs;
            Car.find({dealership_id: { $in: resultArray }}).exec()
                .then(function (cars) {
                    console.log(cars);
                }),
                function (error) {
                    console.log("Could not iterate through through cars: " + error);
                }   
    }, function (error) {
        console.error("Error with the outer promises:", error);
    });

关于javascript - Node.js 无法使用 Promise、Mongoose 和 GET 请求推送到全局数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35074909/

相关文章:

C# - winforms - 以数组形式获取 ListView 中特定列的文本

javascript - 如何从数组中分割并获取选择数据

c - 如何创建结构数组

json - HTTPResponse' 对象没有属性 'decode

javascript - MySQL 注册连接错误

javascript - 3D 线有时会消失

javascript - 如何使用javascript中的变量更改DIV的宽度和高度?

javascript - getElementById 和 getElementsByClassname 都有问题

javascript - 使用原型(prototype)处理事件

Python 使用列表理解读取行(csv 和 json 文件)