【问题标题】:Node.js Promises: Push to array asynchronously & saveNode.js Promises:异步推送到数组并保存
【发布时间】:2015-05-24 23:41:01
【问题描述】:

我目前正在尝试从我通过请求收到的项目列表中推送到数组(Mongo 模型中的属性)。从这些项目中,我遍历它们以查看当前在数据库中的哪一个,如果不是这样,那么我创建一个新项目并尝试保存它。我正在使用 Promise 来完成这项任务,但我无法弄清楚为什么在所有 Promise 都已实现后数组为空。

var q     = require('q');

var items_to_get = ['1', '2', '3']; // example array

var trans = new Transaction({
    items   : []
});

var promises = [];

for (var i = 0; i < items_to_get.length; i++) {

  var ith = i; //save current i, kinda hacky
  var deferred = q.defer(); //init promise

  //find an existing item
  Item.findOne({simcode: items_to_get[ith]}, function(err, item) {
      trans.items.push(item); // push item to transaction
      deferred.resolve(item); // resolve the promise
  });
  promises.push(deferred); // add promise to array, can be rejected or   fulfilled
};

q.allSettled(promises).then(function(result) {
  console.log(trans.items); //is empty
  trans.save();
}

编辑已解决:下面的代码,基于http://jsbin.com/bufecilame/1/edit?html,js,output .. 学分转到@macqm

var items_to_get = ['1', '2', '3'];
var promises     = []; //I made this global

items_to_get.forEach(item) {
  upsertItem(item);
}

q.allSettled(promises).then(function(result) {
  //loop through array of promises, add items 
  result.forEach(function(res) { 
    if (res.state === "fulfilled") {
      trans.items.push(res.value);
    }
  });
  trans.save();
  promises = []; //empty array, since it's global.
}

//moved main code inside here
function upsertItem(item) {
  var deferred = q.defer(); //init promise
  //find an existing item
  Item.findOne({simcode: item}, function(err, item) {
    deferred.resolve(item); // resolve the promise
    // don't forget to handle error cases
    // use deffered.reject(item) for those
  });
  promises.push(deferred); // add promise to array
}

【问题讨论】:

    标签: arrays node.js q


    【解决方案1】:

    这就是我在没有任何第三方库的情况下做到的。

    因为我只是需要推迟并且我在 ES2017 我认为最好不要让不必要的依赖关系过于复杂。

    'use strict';
    
    /**
     * @param {function(*)} callee
     * @param {Array} args
     * @returns {Promise.<*>}
     */
    const defer = (callee, args) => {
        return new Promise(resolve => {
            resolve(callee(...args));
        });
    };
    
    /**
     * @param {Number} one
     * @param {Number} two
     * @param {Number} timeout
     * @returns {Promise.<Number>}
     */
    const asyncFunction = (one, two, timeout) => {
        return new Promise(resolve => {
            setTimeout(resolve, timeout, one + two);
        });
    };
    
    let promises = [];
    promises.push(defer(asyncFunction, [3, 7, 0])); // returns immediately
    promises.push(defer(asyncFunction, [10, 20, 100])); // returns after 100ms
    promises.push(defer(asyncFunction, [55, 45, 50])); // returns after 50ms
    
    Promise.all(promises).then(results => {
        console.log(results);
    });
    

    运行上面的代码,你会得到[ 10, 30, 100 ]

    【讨论】:

      【解决方案2】:

      代替

      promises.push(deferred);
      

      ...试试...

      promises.push(deferred.promise);
      

      此外,由于您的承诺正在解析为无论如何保存的项目,您可以使用 q.allSettled(...) 的结果作为您的项目:

      q.allSettled(promises).then(function(results) {
          trans.items = results;
          trans.save();
      });
      

      【讨论】:

      • 似乎每个结果都是{state: ..., value: ...} 结构的对象,其中value 是您想要的项目,因此您可能需要执行额外的步骤才能将它们取出。
      猜你喜欢
      • 2013-05-29
      • 2013-08-25
      • 2016-06-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-15
      • 2020-06-05
      • 1970-01-01
      相关资源
      最近更新 更多