簡體   English   中英

Node.js無法使用Promise,Mongoose和GET請求推送到全局數組

[英]Node.js Can not push to global array using promises, Mongoose, and GET requests

我無法將需要的結果推送到使用Q Promise庫創建的同步函數中定義的數組。 根據汽車制造商,用戶所在位置的郵政編碼和最大半徑,此功能有3個任務:

  1. 查詢我的經銷店集合以根據輸入的特定制造商用戶檢索經銷店ID。
  2. 然后,我定義一個數組:DealershipID。 該數組將用於將某些經銷商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);
    });
}

如何通過添加到DealershipIDs數組中來使此函數起作用,以便可以將其傳遞給查詢我的Cars集合?

以下函數是我的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.來改善它。

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);
    });
exports.getCarIndexPage = function(req, res) {
var m = req.session.make;
var zipcode = req.session.zipcode;
var radius = req.session.radius;
req.session.valid = null; // Resets session variable

Dealership.find({makes: m}).exec()
    .then(function (ids) {
        var promises = [];
        ids.forEach(function (id) {
            /* Pushing ascynchrounous functions into promise array */
            promises.push(getDistanceWithQPromise(zipcode, id.zip, id._id));
        });
        return Q.all(promises)
            .then(function (promise) {
                var dealershipIDs = []; /* Adding dealership ids to array */
                promise.forEach(function (promiseData) {
                    var distance = promiseData.distance;
                    var id = promiseData.id;
                    if (distance <= radius) {
                        console.log("Adding " + id + " to array");
                        dealershipIDs.push(id); // Adding dealership's id to array
                    }
                });
                console.log("Outside for loop = Size of dealership array: " + dealershipIDs.length); /* Does recognize array size */
                return dealershipIDs;
            }, function (err) {
                console.log(err)
            });
    }).then(function (resultArray) { // Receives the dealership Id array
            Car.find({dealership_id: { $in: resultArray }}).exec()
                .then(function (cars) {
                    renderResult(res, req, cars);
                }),
                function (error) {
                    console.log("Could not iterate through through cars: " + error);
                }   
    }, function (error) {
        console.error("Error with the outer promises:", error);
    });
}

必須修改我的GET請求,以便它使用Q庫返回一個Promise。 我還必須將經銷商ID添加到返回的響應中,以便可以在getCarIndexPage中將其作為承諾值進行訪問。

function getDistanceWithQPromise(userInput, dealerZip, dealerID) {
var deferred = Q.defer();
var request = https.request('https://www.zipcodeapi.com/rest/xApFwnm4tosuL2gX2UDQIGcknN2NIHyfhXVNlhRPFkjrmzpou2edJry7fAVXhtdz/distance.json/' 
        + userInput + '/' + dealerZip + '/mile', function(response) {
    var responseData = '';
    response.on('data', function (data) {
        responseData += data;
    });

    /* Adding the dealer ID to the response string so that I can convert it to JSON before returning the promise */ 
    response.on('end', function() {
        responseData = responseData.slice(0, -1);
        responseData += "," + '"id":' + '"'+dealerID+'"' + "}";

        deferred.resolve(JSON.parse(responseData));
    });

    });

    request.on('error', function(err) {
            deferred.reject(err);
    });

    request.end();
    return deferred.promise;
};

向Ron大喊,建議將異步調用添加到promise數組並使用Q.all。 那正是我所需要的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM