如何在NodeJs中发送回响应之前等待循环完成?

时间:2018-12-15 22:33:39

标签: javascript node.js

我试图在对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();
});

4 个答案:

答案 0 :(得分:3)

首先,应声明SELECT MAX(e.ename) KEEP (DENSE_RANK FIRST ORDER BY e.sal DESC NULLS LAST, e.job) AS name, MIN(e.job) KEEP (DENSE_RANK FIRST ORDER BY e.sal DESC NULLS LAST, e.job) AS job, e.store_id, MAX(e.sal) AS salary, s.city FROM employees e INNER JOIN stores s ON e.store_id = s.store_id GROUP BY e.store_id, s.sity ,并且在声明时应使用块范围(i),以便嵌套的回调函数将使用相同的变量。

您可以检查let中已检索到多少个条目,并在知道所有内容后调用retArr

res.json

答案 1 :(得分:2)

我认为处理这些问题的最简单方法是使用Promises。可以将以回调方式编写的任何异步函数(例如,此User.getUserById)转换为返回诺言的函数。您只需将呼叫包装在一个新的Promise中,并在完成后解决。

对你说。

[{"sesionConcreta":{"grup":{"NumGr":10,"TamGr":200,"subgrupo":[{"NumSub":11,"TamSub":200}],"asignatura":"prop"},"sessio":{"HorasSes":2,"TipoSes":"TEORIA"}},"aula":{"NomAu":"a5105","Capacidad":200,"Tipo":"lab"},"diayHora":{"Dia":"L","Hora":8}}]

然后类似

function promiseGetById(id) {
    return new Promise((resolve, reject) =>
        User.getUserById(id, (err, pat) => resolve(pat))
    );
}

或者,如果您不喜欢诺言,则可以通过拥有一个计数器或在每个回调中递增的东西来实现,然后在计数器为正确值时在回调中添加res.json

答案 2 :(得分:1)

更改所有函数逻辑以返回承诺,并使用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);
});

答案 3 :(得分:-1)

您似乎正在尝试为不那么复杂的算法提取许多函数的方法。以下代码初步提取了请求所需的信息。然后,它填充响应所需的数组并简单地发送它。

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);
});