异步编程新手,所以我无法知道如何执行此操作:
$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
}
由于该过程需要发出HTTP请求,收集数据然后保存到DB,这都需要时间,因此我不希望forEach前进到下一个元素,直到完成。
答案 0 :(得分:3)
使用async包。
async.eachSeries(docs, function iteratee(product, callback) {
// 1. Search ...
google(keyword, function (err, res) {
if (err) {
console.error(err)
callback(results) // this will send a fail callback.
}
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
callback(null, results) // this is a success callback
}
}, processData); // 3. send all results to processData when done
});
注意:回调的行为类似于return。一旦回调符合价值,它就不会继续进行。现在它将发送下一个产品的请求。
答案 1 :(得分:2)
由于forEach是同步的并且请求是异步的,因此无法完全按照您的描述进行操作。然而,你可以做的是创建一个处理docs数组中的一个项目并删除它的函数,然后当你完成处理时,转到下一个:
chcp 1252
::::::::::::::::::::::::::::::::::::::::::::
:: Run as admin
::::::::::::::::::::::::::::::::::::::::::::
@echo off
CLS
ECHO.
ECHO =============================
ECHO The name of the main folder?
ECHO =============================
:init
setlocal DisableDelayedExpansion
set "batchPath=%~0"
for %%k in (%0) do set batchName=%%~nk
set "vbsGetPrivileges=%temp%\OEgetPriv_%batchName%.vbs"
setlocal EnableDelayedExpansion
:checkPrivileges
NET FILE 1>NUL 2>NUL
if '%errorlevel%' == '0' ( goto gotPrivileges ) else ( goto getPrivileges )
:getPrivileges
if '%1'=='ELEV' (echo ELEV & shift /1 & goto gotPrivileges)
ECHO.
ECHO **************************************
ECHO Invoking UAC for Privilege Escalation
ECHO **************************************
ECHO Set UAC = CreateObject^("Shell.Application"^) > "%vbsGetPrivileges%"
ECHO args = "ELEV " >> "%vbsGetPrivileges%"
ECHO For Each strArg in WScript.Arguments >> "%vbsGetPrivileges%"
ECHO args = args ^& strArg ^& " " >> "%vbsGetPrivileges%"
ECHO Next >> "%vbsGetPrivileges%"
ECHO UAC.ShellExecute "!batchPath!", args, "", "runas", 1 >> "%vbsGetPrivileges%"
"%SystemRoot%\System32\WScript.exe" "%vbsGetPrivileges%" %*
exit /B
:gotPrivileges
setlocal & pushd .
cd /d %~dp0
if '%1'=='ELEV' (del "%vbsGetPrivileges%" 1>nul 2>nul & shift /1)
::::::::::::::::::::::::::::
::START
::::::::::::::::::::::::::::
::Dialogwindow.
@echo off
title message
echo Skriv nedan^^!
set/p "Projektnamn=>"
:: Creates the folder structure
md "%~dp0"%Projektnamn%
md "%~dp0""%Projektnamn%"/"1. Projektpärm"
md "%~dp0""%Projektnamn%"/"1. Projektpärm"/"1. Tekniska specifikationer"
md "%~dp0""%Projektnamn%"/"1. Projektpärm"/"2. ÄTA,Beställning & Fakturering"
md "%~dp0""%Projektnamn%"/"1. Projektpärm"/"3. Tidplan"
md "%~dp0""%Projektnamn%"/"1. Projektpärm"/"4. Projektmöten"
md "%~dp0""%Projektnamn%"/"1. Projektpärm"/"5. Dagbok"
md "%~dp0""%Projektnamn%"/"1. Projektpärm"/"6. Kvalitet"
:: Genväg enlinjeschema, se kod för genväg
md "%~dp0""%Projektnamn%"/"2. Kretsschema"
md "%~dp0""%Projektnamn%"/"2. Kretsschema"/"1. Konstruktionsunderlag från kund"
md "%~dp0""%Projektnamn%"/"3. Stationsdokumentation"
md "%~dp0""%Projektnamn%"/"3. Stationsdokumentation"/"1. Enlinjeschema"
md "%~dp0""%Projektnamn%"/"3. Stationsdokumentation"/"2. Blockschema"
md "%~dp0""%Projektnamn%"/"3. Stationsdokumentation"/"3. Förreglingsschema"
md "%~dp0""%Projektnamn%"/"3. Stationsdokumentation"/"4. Ritningsnummer"
md "%~dp0""%Projektnamn%"/"4. Skåpsdokumentation"
md "%~dp0""%Projektnamn%"/"4. Skåpsdokumentation"/"1. Skåpslayout"
md "%~dp0""%Projektnamn%"/"4. Skåpsdokumentation"/"2. Apparatlista"
md "%~dp0""%Projektnamn%"/"4. Skåpsdokumentation"/"3. Förbindningstabell"
md "%~dp0""%Projektnamn%"/"4. Skåpsdokumentation"/"4. Skyltlista & Etiketter"
:: Skapar RELATIVA Genvägarna
mklink /D "%~dp0%Projektnamn%\1. Projektpärm\7. Enlinjeschema" "..\3. Stationsdokumentation\1. Enlinjeschema"
mklink /D "%~dp0%Projektnamn%\1. Projektpärm\8. Blockschema" "..\3. Stationsdokumentation\2. Blockschema"
mklink /D "%~dp0%Projektnamn%\1. Projektpärm\9. Förreglingsschema" "..\3. Stationsdokumentation\3. Förreglingsschema"
mklink /D "%~dp0%Projektnamn%\1. Projektpärm\10. Skåpslayout" "..\4. Skåpsdokumentation\1. Skåpslayout"
pause
修改强>
将产品从数据库移至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 );
} );
}
变量,并将productsToProcess
更改为不再需要参数。
答案 2 :(得分:0)
您无法在Array.prototype.forEach()
内等待异步操作。
考虑到您用于Google的请求所使用的库与Promises不兼容,使用Async可能是您案例中的快速解决方案(对于大型项目或Promise兼容库,我建议使用Promise方式)
Async map允许你在里面使用异步操作,因为它等待回调。
在你的情况下,我猜是这样的:
async.map(products, function(product, callback) {
var keyword = product['vendor'] + ' "' + product['mpn'] + '"';
google( keyword, function (err,res) {
if (err) {
// if it fails it finish here
return callback(err);
}
// using map here makes it easier to loop through the results
var results = res.links.map(function(link) {
return {
title: link.title,
href: link.href,
description: link.description
};
});
callback(null, results);
});
}, processData);
如果您对上述代码有任何疑问,请与我们联系。