[英]Wait for httpRequests to finish before sending response - ParseServer
[英]How to wait for a loop to finish running before sending back a response in NodeJs?
我试图在对URL的GET请求之后将对象数组发送回去,但是我不知道如何构造逻辑,因此返回数组在发送给客户端之前会完全填充。
下面是我的服务器端代码,用于响应请求。 我之前在代码中使用过passport.js来创建登录门户和用户对象。 我正在尝试从发出请求的用户那里获取“连接”数组,并将其发送回带有连接名称和图片的对象数组。 我知道以下代码在语法上是不正确的,但这是我要完成的工作的概述。 我尝试过以回调的方式进行操作,但这一直使我陷入困境,因为我无法找出正确的逻辑。
router.get('/data', function(req, res, next) {
var IdArr = req.user.connections;
var retArr = [];
function getUsers() {
for (i = 0; i < IdArr.length; i++) {
User.getUserById(IdArr[i], function(err, patient) {
retArr[i] = {name:patient.name, pic:patient.profileImage};
});
}
}
function getDataAndSend() {
function(getUsers(), function sendRes() { // I know this is incorrect syntax
console.log(retArr);
res.json(retArr);
});
}
getDataAndSend();
});
首先,您应该声明i
,并且在进行声明时应使用block-scope( let
),以便嵌套的回调函数将使用相同的变量。
您可以检查retArr
中已经检索了多少条目,并在知道所有内容后调用res.json
。
router.get('/data', function(req, res, next) {
var IdArr = req.user.connections;
var retArr = [];
for (let i = 0; i < IdArr.length; i++) {
User.getUserById(IdArr[i], function(err, patient) {
retArr[i] = {name:patient.name, pic:patient.profileImage};
if (Object.keys(retArr).length === IdArr.length) res.json(retArr);
});
}
});
我认为处理这些问题的最简单方法是使用Promises。 任何以回调方式编写的异步函数(例如,此User.getUserById)都可以转换为返回承诺的函数。 您只需将呼叫包装在一个新的Promise中,并在完成后解决。
说你的情况。
function promiseGetById(id) {
return new Promise((resolve, reject) =>
User.getUserById(id, (err, pat) => resolve(pat))
);
}
然后像
Promise.all(IdArr.map(id => promiseGetById(id))).then(arr =>
res.json(
arr.map(patient => ({ name: patient.name, pic: patient.profileImage }))
)
);
或者,如果您不喜欢诺言,则可以通过拥有一个计数器或在每个回调中递增的东西来实现它,然后在计数器为正确值时在回调中添加res.json。
更改所有函数逻辑以返回承诺,并使用async/await
来使代码清晰。
const getUserById = (id) => {
return new Promise((resolve, reject) => {
User.getUserById(IdArr[i], function(err, patient) {
resolve({name:patient.name, pic:patient.profileImage});
});
});
}
const getAllUsers = async(idArr) => {
const retArr = [];
// for...of loop to await without continuing the loop
// but this will execute only sequentially
for (let id of idArr) {
const ret = await getUserById(id);
retArr.push(ret);
}
// for parallel execution, use Promise.all()
await Promise.all([...idArr.map(id => getUserById(id))]);
return retArr;
}
router.get('/data', async (req, res, next) => {
var IdArr = req.user.connections;
var retArr = await getAllUsers(IdArr);
console.log(retArr);
res.json(retArr);
});
您似乎正在尝试为不那么复杂的算法提取许多函数的方法。 以下代码初步提取了请求所需的信息。 然后,它填充响应所需的数组并简单地发送它。
router.get('/data', (req, res, next) => {
const idArray = req.user.connections;
let responseArray = [];
// loop to populate responseArray
for (let id of idArray) {
User.getUserById(id, (err, patient) => {
// add to the end of the array the patient informations
responseArray.push({
name: patient.name,
pic: patient.profileImage
});
});
}
// send back responseArray
res.json(responseArray);
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.