【问题标题】:Async Push data to Array in Node异步将数据推送到节点中的数组
【发布时间】:2017-06-10 05:15:58
【问题描述】:

我在另一个 mongoose 查询中调用 mongoose 查询。当我将结果推送到数组时,当我最后检查它时它是空的。经过大量搜索,发现问题是异步执行。但找不到解决问题的方法。我的代码如下。

    Bus.find().exec(function(err,buses) {

        if(err)
            console.log(err);
        if (buses[0] != null){
            const cords = [];
            buses.forEach( function (bus) {
                // console.log(bus);
                    Position.findOne({"busId": bus.busId},{}, {sort : {'time' : -1}}, function (err, position) {
                        cords.push(position);
                        console.log(cords);
                        // console.log(position);
                    });
                    console.log(cords);
                },
                function (err) {
                    if (err){
                        console.log(err,"Errrrrrrrrrrrrr");
                    }
                });
            console.log(cords);
            res.json({cords: cords});
            }

【问题讨论】:

    标签: node.js mongodb asynchronous


    【解决方案1】:

    好吧,您的代码存在许多问题,但其中最主要的一个事实是,您无法将在回调中收到的值保存或操作到该回调之外的任何内容。您的示例已(为清楚起见重写):

    var result = []
    arry.forEach(function(opt) {
      async.call(args, function(err,value) {
        result.push(value)
      })
    })
    // result is empty here!
    

    无法按预期工作,因为您无法知道内部回调何时完成。

    根据定义,回调会在未来的某个时间触发,由于你不知道什么时候,你必须使用传递给回调的结果进行所有计算 在回调本身!

    否则会产生不一致的结果。

    更新 - 重新评论

    (注意:在火车上匆忙在 iPad 上打字,如果需要,稍后会修复。

    最好的方法是使用 Promises 来聚合结果。这是一个天真的例子:

    /* 
     * given a value and an optional array (accum),
     * pass the value to the async func and add its result to accum
     * if accum is not an array, make it one
     * return accum
     */
    
    var do_something = (value, accum) => {
      // on first pass, accum will be undefined, so make it an array
      accum = Array.isArray(accum) ? accum : []
      return new Promise((resolve, reject) => {
        async_func(value, (err, res) => {
          if(err) {
            reject(err)
          }
          accum.append(res)
          resolve(accum)
        })
      })
    }   
    
    /* 
     * for each member of input array, apply do_something
     * then operate on accumulated result.
     */
    
    Promise.map(input, do_something)
      .then(results => {
        // results will contain the accumulated results from all
        // the mapped operations
      })
      .catch(err => {
        throw err
      })
    

    更新 - 每条评论

    仅使用回调,您可以使用以下方法获得相同的结果:

    const inputs = [...] // array of inputs to pass to async function
    
    const expected_num_of_results = inputs.length
    
    let results = []
    
    const onComplete = (results) => {
      // do something with completed results here
      console.log(`results: ${results}`);
    }
    
    const onResult = (err, res) => { // callback to async_func
      if(err) {
        throw new Error(`on iteration ${results.length+1}: ${err}`)
      }
    
      results.push(res) // save result to accumulator
    
      if( results.length >= expected_num_of_results) { // are we done?
        onComplete(results) // process results
      }
    }
    
    // example async func - REPLACE with actual async function
    const async_func = (val,cb) => {
      // call callback with no error and supplied value multiplied by 2
      cb(null,val*2)
    }
    
    // wrapper that takes one value 
    // and calls async_func with it and predefined callback
    const do_async = (value) => { 
      async_func(value, onResult)
    }
    
    // process inputs
    inputs.forEach(do_async)
    

    所以:

    const inputs = [1,2,3,4,5]
    

    将打印:

    results: 2,4,6,8,10
    

    【讨论】:

    • 你能给我一个例子来说明如何用回调来做这件事!如果可以的话,这将是一个很大的帮助!
    猜你喜欢
    • 2020-12-19
    • 2022-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-24
    • 2016-03-29
    • 2021-06-25
    • 2015-11-15
    相关资源
    最近更新 更多