In my project I have two functions that retrieve respectively the number of completed tasks, and the number of uncompleted tasks. (I use NeDB but it does not matter).
After that, I want to add together these two numbers.
Here is my code :
var completed = 0
, uncompleted = 0;
// Get completed tasks
db.find({ completed: true }, function (err, tasks) {
completed = tasks.length;
console.log(completed); // output 7
});
// Get uncompleted tasks
db.find({ completed: false }, function (err, tasks) {
uncompleted = tasks.length;
console.log(uncompleted); // output 3
});
// This line is executed before the lines above
console.log(completed+uncompleted); // output 0 (I would like to output 10)
As you see the last line output 0 because it is executed before the two functions have finished.
So my question is how to make the last line output 10 ?
I think I have to use promises, but I read a lot of topics on SO and there is a lot of different approaches (with promise, then, done, deffered, array of promises, functions in variables ...) so I'm a little bit lost.
I wanted to know what is the correct way to do that :)
I tried this code, but I think I am completely mistaken ...
var completed = 0 , uncompleted = 0; // Get completed tasks var getCompleted = function(){ return db.find({ completed: true }, function (err, tasks) { completed = tasks.length; console.log(completed); // output 7 }); } // Get uncompleted tasks var getUncompleted = function(){ return db.find({ completed: false }, function (err, tasks) { uncompleted = tasks.length; console.log(uncompleted); // output 3 }); } var promises = []; promises.push(getCompleted()); promises.push(getUncompleted()); $.when.apply($, promises).done(function () { console.log(completed+uncompleted); // output 0 });
The NeDB
library you are using does not return promises - you can perform your work in nested callbacks like this:
db.find({completed: true}, function(err, completeTasks) {
db.find({completed: false}, function(error, incompleteTasks) {
console.log(completeTasks.length + incompleteTasks.length);
});
})
If you want to use Promises, first you'll need to promisify any asynchronous tasks that don't return a promise
In your case
function dbFindPromise(db, params) {
return new Promise((resolve, reject) =>
db.find(params, (err, result) => {
if(err) {
reject(err);
} else {
resolve(result);
}
})
)
};
Then, using this promisified db find, your code can be written as
Promise.all([
dbFindPromise(db, { completed: true }).then(tasks => {
console.log(tasks.length);
return tasks.length;
}),
dbFindPromise(db, { completed: false }).then(tasks => {
console.log(tasks.length);
return tasks.length;
})
]).then(([completed, uncompleted]) => {
console.log(completed + uncompleted);
});
Alternatively, using jquery Deferred and when - first the "promisified" function
function dbFindPromise(db, params) {
var deferred = $.Deferred();
db.find(params, (err, result) => {
if(err) {
deferred.reject(err);
} else {
deferred.resolve(result);
}
});
return deferred.promise();
};
Then to use it:
$.when(dbFindPromise(db, { completed: true }).then(tasks => {
console.log(tasks.length);
return tasks.length;
}), dbFindPromise(db, { completed: false }).then(tasks => {
console.log(tasks.length);
return tasks.length;
})
).done((completed, uncompleted) => {
console.log(completed + uncompleted);
});
So, native promises, code A and B, jquery Promises is code C and D
But, you can use code A with code D or code C with code B - because Promises should behave the same regardless of where they came from (in this case, native vs jquery)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.