【问题标题】:node.js async array save data to mongodbnode.js 异步数组将数据保存到 mongodb
【发布时间】:2013-05-29 18:12:14
【问题描述】:

我有一个字符串

var my_str = "Jenny [id:51], david, Pia [id:57], Aston [id:20], Raj, ";

我将其发送到函数 convert_to_array(my_str) 并希望得到类似的回报

[all: [51, 72, 57, 20, 73], new: [72, 73]]

这里,72 和 73 是新插入到 mongodb 数据库的文档。

这就是我正在做的:

function convert_to_array(text) {
if(text && text !== '') {

    var text_arr = text.split(', ');
    text_arr.pop();

    var arr = new Array();
    var new_profiles = new Array();
    var all_profiles =  new Array();

    for(var i = 0; i < text_arr.length; i++) {
        var pair = text_arr[i].split('[id:');

        // Its already existing, just add it to the array
        if(pair[1]) {
            all_profiles.push(pair[1].split(']')[0]);

        // Else create a new profile and pass the _id
        } else {

            // Save to db first
            var profileObj = new Profile({name: pair[0], automated: true});
            profileObj.save(function(err, data) {

                if(err) throw err;

                all_profiles.push(String(data._id));
                new_profiles.push(String(data._id));
            });
        }
    }
    arr = {all: all_profiles, new: new_profiles};
    return arr;
}
}

使用这段代码,我只得到这个(或类似的东西,我不记得确切的输出)

    [all: [51, 57, 20], new: []]

该项目保存在数据库中,我可以看到。但是由于节点本质上是非阻塞的,所以 for 循环在数据保存到数据库之前完成并返回,并将 id 推送到 aray。我尝试了异步,但仍然无法弄清楚如何解决这个问题。

我添加了一些 console.logs 来看看它是如何执行的,这里是:

yes existing: 51
oh! doesnt exist. creating: david
yes existing: 57
yes existing: 20
oh! doesnt exist. creating: Raj
GET /page/delete_later 200 4ms
Ok created now: 72
Ok created now: 73

我很困惑如何编写节点友好的代码!

【问题讨论】:

    标签: javascript node.js asynchronous mongoose


    【解决方案1】:

    您需要更改您的 convert_to_array 函数,以便它在结果完成时调用回调,而不是返回结果返回值。

    function convert_to_array(text, callback) {
       // do some stuff, call this when done:
       //    callback(null, arr);
       // or this on error:
       //    callback(err);
    }
    

    现在你的结果准备好了吗?这是处理所有text_arr 项目的时间(即所有对profileObj.save 的调用都已完成)。在代码中表达这一点的最简单方法可能是使用异步模块(npm install async):

    var async = require('async');
    // ...
    
    function convert_to_array(text, callback) {
      if(text && text !== '') {
    
        var text_arr = text.split(', ');
        text_arr.pop();
    
        var arr = new Array();
        var new_profiles = new Array();
        var all_profiles =  new Array();
    
        async.eachSeries(text_arr, function(it, done) {
          var pair = text_arr[i].split('[id:');
    
          // Its already existing, just add it to the array
          if(pair[1]) {
            all_profiles.push(pair[1].split(']')[0]);
            next(); // !important! tell async we are done
          // Else create a new profile and pass the _id
          } else {
            // Save to db first
            var profileObj = new Profile({name: pair[0], automated: true});
            profileObj.save(function(err, data) {
                if(err) {
                  // throw err; // use callback instead of throw for error handling
                  next(err);
                  return;
                }
                all_profiles.push(String(data._id));
                new_profiles.push(String(data._id));
                next(); // !important! tell async we are done
            });
        }, function(err) { 
          arr = {all: all_profiles, new: new_profiles};
          callback(err, arr);
        }
    
      } else {
    
        callback(null, undefined); // alter depending on your requirements
      }
    }
    

    【讨论】:

    • 谢谢米罗斯拉夫!我会尽快试试这个。实际上,我为此使用了 async.eachSeries,但无法让它返回我想要的。我认为它是完成 .save() 后的 next() 调用! async 的自述文件真的很混乱:p
    猜你喜欢
    • 2015-05-24
    • 1970-01-01
    • 2020-06-05
    • 1970-01-01
    • 2019-12-05
    • 2019-11-03
    • 1970-01-01
    • 1970-01-01
    • 2022-01-22
    相关资源
    最近更新 更多