I am currently trying to push to an array (attribute within a Mongo Model), from a list of items I receive through a request. From those items, I loop through them to see which one is currently in the db and if that is not the case, then I create a new Item and try to save it. I am using promises to accomplish this task but I am unable to figure out why the array is empty after all the promises have fulfilled.
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();
}
EDIT Resolved: Code bellow, based on http://jsbin.com/bufecilame/1/edit?html,js,output .. credits go to @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
}
A promise is used to handle the asynchronous result of an operation. JavaScript is designed to not wait for an asynchronous block of code to completely execute before other synchronous parts of the code can run. With Promises, we can defer the execution of a code block until an async request is completed.
In JavaScript, promises are special objects that help you perform asynchronous operations. You can create a promise using the Promise constructor. You need to pass an executor function to it. In the executor function, you define what you want to do when a promise returns successfully or when it throws an error.
all() Method: Fulfillment: The returned promise is fulfilled, If the passed iterable is empty, then this method returns an promise synchronously which is already resolved. If all of the passed promises are fulfill, the returned Promises are fulfilled asynchronously.
Async/Await is used to work with promises in asynchronous functions. It is basically syntactic sugar for promises. It is just a wrapper to restyle code and make promises easier to read and use. It makes asynchronous code look more like synchronous/procedural code, which is easier to understand.
This is how I did it without any 3rd party libraries.
Since I just needed to defer and I'm on ES2017 I figured it was best not to over complicate things with unnecessary dependencies.
'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);
});
Run the above code and you'll get [ 10, 30, 100 ]
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With