Tuesday 10 December 2019

javascript - Making forEach wait for callback




New to async programming so I just can't figure how to do this:



$results = [];

products.forEach(function (product) {

// 1. Search ...
google(keyword, function (err, res) {
if (err) console.error(err)


for (var i = 0; i < res.links.length; ++i) {
var result = res.links[i];
var obj = {
title: res.links[i].title,
href: res.links[i].href,
description: res.links[i].description
}
results.push(obj); // 2. store each result in results Array
}
}, processData); // 3. send all results to processData when done


// 5. NOW, itereate further ...

});

function processData(results) {
console.log('processing data');
// 4. save results to DB
}



Since the process requires making HTTP requests, collecting data and then saving to DB which all takes time, so I don't want forEach to advance to the next element until one is done.


Answer



Since the forEach is synchronous and the request is asynchronous, there is no way to do it exactly as you describe. What you can do however is to create a function that handles one item from the docs array and removes it, then when you're done processing, go to the next:



var results;
var productsToProcess;
MongoClient.connect( 'mongodb://localhost:27017/suppliers', function ( err, db ) {
assert.equal( null, err );
var findDocuments = function ( db ) {

var collection = db.collection( 'products' );
collection.find( {
$and: [ {
"qty": {
$gt: 0
}
}, {
"costex": {
$lte: 1000.0
}

} ]
}, {
"mpn": 1,
"vendor": 1,
"_id": 0
} ).limit( 1 ).toArray( function ( err, products ) {
assert.equal( err, null );
productsToProcess = products;
getSearching();
db.close();

} );
}
findDocuments( db );
} );

function getSearching() {
if ( productsToProcess.length === 0 ) return;
var product = productsToProcess.splice( 0, 1 )[0];
var keyword = product[ 'vendor' ] + ' "' + product[ 'mpn' ] + '"';
google( keyword, function ( err, res ) {

if ( err ) console.error( err )
for ( var i = 0; i < res.links.length; ++i ) {
var result = res.links[ i ];
var obj = {
title: res.links[ i ].title,
href: res.links[ i ].href,
description: res.links[ i ].description
}
results.push( obj );
}

}, processData );
}

function processData( results ) {
MongoClient.connect( 'mongodb://localhost:27017/google', function ( err, db ) {
assert.equal( null, err );
// insert document to DB
var insertDocuments = function ( db, callback ) {
// Get the documents collection
var collection = db.collection( 'results' );

// Insert some documents
collection.insert( results, function ( err, result ) {
assert.equal( err, null );
console.log( "Document inserted" );
callback( result );
db.close();
} );
}
insertDocuments( db, getSearching );
} );

}


EDIT



Moved the products from the database to the productsToProcess variable and changed the getSearching() to no longer require a parameter.


No comments:

Post a Comment

php - file_get_contents shows unexpected output while reading a file

I want to output an inline jpg image as a base64 encoded string, however when I do this : $contents = file_get_contents($filename); print &q...