函数在foreach结束前返回map

时间:2017-05-24 17:23:26

标签: javascript node.js promise co

我有这个小程序,通过乘以一个小时和一些小时来计算总数。

我遇到的问题是函数getTasks()总是返回一个空映射。 当我记录在地图中输入的字段时,它们不是空的,但是在函数返回地图后输入它们。 所以我有点困惑为什么会发生这种情况。

function getTask(taskId) {
  return rp({
    uri: `${url}/tasks/${taskId}`,
    auth: {
      user: 'user',
      password,
      sendImmediately: false
    },
    json: true
  }).then((task) => {
    return task;
  });
}

function getTasks(entries) {
  const taskIds = [];

  entries.forEach((entry) => {
    const taskId = entry.day_entry.task_id;
    if (!taskIds.includes(taskId)) {
      taskIds.push(taskId);
    }
  });

  const taskRateMap = new Map();

  taskIds.forEach((taskId) => {
    return Promise.resolve(getTask(taskId)).then((res) => {
      if (res.task.id === taskId) {
        taskRateMap.set(taskId, res.task.default_hourly_rate);
        console.log(taskRateMap);
      }
    });
  });
  return taskRateMap;
}

function calculateTasksTotals(id) {
  return co(function* calculateTotalsGen() {
    let total = 0;

    const entries = yield getEntriesForProject(id);

    const tasks = getTasks(entries);

    entries.forEach((entry) => {
      const rate = tasks.get(entry.day_entry.task_id);
      total += rate * entry.day_entry.hours;
    });
    return total;
  });
}

calculateTasksTotals(id)

3 个答案:

答案 0 :(得分:0)

您的承诺存在问题。尝试使用Promise.all()提供所有承诺作为输入,并仅在所有承诺都已解决后返回您的地图。 否则直接返回你的Promise.all()并在调用方法中创建地图。

类似于:

const tasksPromises = [];
  taskIds.forEach((taskId) => {
    tasksPromises.push(getTask(taskId)); 
  });
return Promise.all(tasksPromises);

然后在你的调用方法中通过then解析promises,你将把回调函数的参数作为一个数组,其中每个元素都是相应promise的返回值。

答案 1 :(得分:0)

我相信这种情况正在发生,因为taskRateMap在返回之前没有被填充。您可能想要查看Promise.all() 并考虑包装

promises = taskIds.map((taskId) => {
return Promise.resolve(getTask(taskId)).then((res) => {
  if (res.task.id === taskId) {
    return [taskId, res.task.default_hourly_rate];
    console.log(taskRateMap);
  }
});

return Promise.all(promises).then(v => /* taskRateMap*/)

答案 2 :(得分:0)

您的代码存在多个问题:

  1. 首先,只要您在函数中涉及任何异步操作,该函数的结果将是异步的。你根本无法同步返回它。异步操作稍后完成。函数本身在异步操作完成之前返回。

  2. 因此,您从使用异步操作的任何函数返回一个promise,并且调用者使用该promise来知道事情何时完成或获得最终结果。

  3. 您的函数getTask()没问题。它返回一个承诺。该函数内的.then()是多余的,不需要,因为task似乎已经是承诺的已解析值。

  4. 您的函数getTasks()正在尝试同步返回taskRateMap,但正如您在测试中看到的那样,所有承诺都没有得到解决,因此{{1}中没有值尚未。在我的代码版本中,我在内部使用taskRateMap来了解所有Promise.all()操作何时完成,并且我返回一个已解析值为getTask()对象的承诺。

  5. taskRateMap的调用者可以使用该承诺和getTasks()处理程序来访问.then()对象。

  6. 这是实现taskRateMap的一种方式:

    getTasks()