节点中的异步功能仅在发送响应后运行

时间:2018-08-07 06:14:32

标签: node.js express asynchronous

我有方法:

const getTaskOrCategoryRecursive = async (type, id)=>{
    const rslt = await type.findOne.call(type, {_id:id},{}, standardOptions, err=>{
        if(err){
            return({err: err});
        }
    });

    const result = rslt.toObject();
    const tasks = result.tasks;
    const events = result.events;
    result.children = {};
    result.children.tasks = tasks.map(async taskId=>{
        const taskIdString = taskId.toString();
        const rtrn = await getTaskRecursive(taskIdString, err=>{
            if(err){
                return({err: err});
            }
        });
        return rtrn;
    });
    result.children.events = events.map(async eventId=>{
        const eventIdString = eventId.toString();
        await Event.findOne({_id:eventIdString}, standardOptions,err=>{
            if(err){
                return({err: err});
            }
        });
    });
    return result;
}

有两种方法调用它:

const getTaskRecursive = (taskId)=>{
    return getTaskOrCategoryRecursive(Task, taskId)

}

const getCategoryRecursive=(categoryId)=>{
    return getTaskOrCategoryRecursive(Category,categoryId);
};

由函数调用

router.get('/:id', verifyToken, async (req,res)=>{
    Branch.getCategoryRecursive(req.params.id)
        .then(
            (cat)=>{
                res.status(200).send(cat);
            },
            (err)=>{
                res.status(500).send(err);
            }
        )
});

当我尝试运行程序时,首先运行getCategoryRecursive方法,然后运行res.status(200).send(cat);,然后运行getTasksRecursive方法,该方法获取响应中要发送的对象的子级。 getTasksRecursive执行了应有的操作,但是在发送响应后它正在运行,因此该对象为空。

如何在发送响应之前使异步方法运行?

更新:使用Aritra Chakraborty的答案,我将其更改为以下内容,并且可以正常工作。

首先,我将.map分解为一个新函数:

const getAllTasksRecursive = async(taskIds)=>{
    const rtrn = await Promise.all(
        taskIds.map(
            async taskId=>{
                return await getTaskRecursive(taskId.toString(), err=>{if(err){return {err:err}}});
            }
        )
    )
    return rtrn;
}

然后我在上一个函数中使用:

result.children.tasks = await getAllTasksRecursive(tasks);

现在,我将数据返回到响应中。

1 个答案:

答案 0 :(得分:1)

那是因为内部的mapforeach看起来像这样:

Array.prototype.forEach = function (callback) {
  // this represents our array
  for (let index = 0; index < this.length; index++) {
    // We call the callback for each entry
    callback(this[index], index, this)
  }
}

它会正确调用回调,但是在运行下一个回调之前不会等待回调完成。

因此,您需要一个async foreach

async function asyncForEach(array, callback) {
    for (let index = 0; index < array.length; index++) {
        await callback(array[index], index, array)
    }
} 

请注意,如何await进行回调。

您的代码必须是这样的:

const start = async () => {
  await asyncForEach([1, 2, 3], async (num) => {
    await waitFor(50)
    console.log(num)
  })
  console.log('Done')
}
start()

引用:https://codeburst.io/javascript-async-await-with-foreach-b6ba62bbf404这篇文章过去对我有很大帮助。