Node.js Promises:异步推送到数组并保存
Posted
技术标签:
【中文标题】Node.js Promises:异步推送到数组并保存【英文标题】:Node.js Promises: Push to array asynchronously & save 【发布时间】: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
【问题讨论】:
【参考方案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
是您想要的项目,因此您可能需要执行额外的步骤才能将它们取出。以上是关于Node.js Promises:异步推送到数组并保存的主要内容,如果未能解决你的问题,请参考以下文章
从 Array 推送到 Azure 队列覆盖消息?[node.JS]
Node.js 无法使用 Promise、Mongoose 和 GET 请求推送到全局数组
Node.js assert.throws 带有异步函数(Promises)