问题
I have a very specific question and hopefully someone can lend me a hand here. I'm quite green when it comes to Javascript much more when it comes to NodeJS.
I am using lodash's _.forIn functionality to traverse and add into an object that's inside an array. The whole thing looks something like this:
[
{ id: 20,
keywords: 'shirts'
},
{ id: 18,
keywords: 'shoes'
}
]
Basically it's list of keywords saved in in the db elasticsearch. I'm trying to find a way to add into this object a counter of the number of results these keywords would return.
This count will come from an elasticsearch setup that we use to search our product database with.
The output I'd like to get would be something like this:
[
{ id: 20,
keywords: 'shirts',
count: 4
},
{ id: 18,
keywords: 'shoes',
count: 15
}
]
This is the code I have right now:
function get_list( data ) {
var list_data = data;
var list = _.forIn( data, function( item, n, list_data ) {
get_count( item, function( count_number ) {
list_data[n].count = count_number;
})
});
console.log( list, list_data );
}
function get_count( item, callback ) {
var query = { // elasticsearch query here };
// elasticsearch query here, that returns the count in a callback
es.count( query, function(count_number) { callback(count_number) } );
}
When I run this, the console will show an unchanged array. I've checked all the returned data on each function, everything checks out. I just can't seem to get the data right on neither list nor list_data.
PS. This isn't my actual code but it's pretty much the gist of it, so there may be some typos.
Also, list and list_data is a result of me trying to figure out how this works. I've tried reading up on how JS callbacks work but nothing I've seen seem to be able to help me with my problem.
回答1:
You can check the list_data object only after all the callbacks have finished.
If you want to validate that your get_count function is working you can move the console.log inside the callback, this will result in multiple logs of the list_data in the console.
function get_list( data ) {
var list_data = data;
var list = _.forIn( data, function( item, n, list_data ) {
get_count( item, function( count_number ) {
list_data[n].count = count_number;
console.log( list, list_data );
})
});
}
function get_count( item, callback ) {
var query = { // elasticsearch query here };
// elasticsearch query here, that returns the count in a callback
es.count( query, function(count_number) { callback(count_number) } );
}
In order to do this i recommend using the async module with is pretty good to handle asynchronous calls like yours.
Here is the module link so you can start using it: https://github.com/caolan/async
Here is how i would implement the async module in our case:
var async = require('async');
function get_list(data) {
var list_data = data;
//Transform all the list_data objects adding the count prop.
async.map(list_data, get_count, function(err, results) {
console.log(results);
});
}
function get_count(item, callback) {
var query = { // elasticsearch query here
};
// elasticsearch query here, that returns the count in a callback
es.count(query, function(count_number) {
//add the new prop to the item
item.count = count_number;
//return the transformed object
callback(null, item);
});
}
来源:https://stackoverflow.com/questions/29852361/javascript-return-a-value-to-a-variable-outside-of-a-callback-function