[英]Node.js Can not push to global array using promises, Mongoose, and GET requests
我無法將需要的結果推送到使用Q Promise庫創建的同步函數中定義的數組。 根據汽車制造商,用戶所在位置的郵政編碼和最大半徑,此功能有3個任務:
任務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.