免责声明:非工程师,JS的新手
嘿所有 - 我试图利用async.js模块将一组函数链接在一起。我想要的输出是迭代mapData
(对象数组),然后将它传递给最终函数(现在 - 只是console.log(结果)。
async.waterfall([
function( callback ) {
getCoords ( function( data ) {
mapData = data;
});
callback(null, mapData);
},
function( mapData, callback ) {
//getEmail ( mapData );
callback( null, mapData );
}
], function( err, result ) {
console.log( result );
});
但是,getCoords
包含另一个异步函数(找到here)。我所看到的是第一个回调(null,mapData)在它返回之前发生,导致null结果。
如何构建此结构,以便getCoords
在继续下一个块之前返回mapData
?我可能错过了一些非常明显的东西,谢谢!
答案 0 :(得分:8)
回调乐趣......您需要了解程序流在使用回调时的工作原理。这可以通过一个非常简单的例子看出。
示例:强>
function doWork( callback ) {
console.log( 2 );
setTimeout(callback, 1000);
}
function master () {
console.log(1);
doWork(function () {
console.log(3);
});
console.log(4);
}
master();
预期结果将是适配器顺序1,2,3,4中的控制台日志。但是当运行该示例时,您会看到一些奇怪的事情,因为日志乱序为1,2,4,3。这是因为日志记录在doWork
完成后发生3,而在启动doWork
后发生4记录,而不是等待它完成。
<强>异步:强>
您可以使用异步库做很多事情,但大多数要记住的重要事情是回调函数总是接收错误,因为第一个参数后跟您要传递的参数到列表中的下一个功能。
您链接到的gist未设置为以此方式返回。您可以修复它或在代码中处理它。首先让我们按原样使用该功能:
使用现有的getCoords:
async.waterfall([
function( callback ) {
// getCoords only returns one argument
getCoords ( function( mapData ) {
// First argument is null because there
// is no error. When calling the waterfall
// callback it *must* happen inside the getCoords
// callback. If not thing will not work as you
// have seen.
callback( null, mapData);
});
},
function( mapData, callback ) {
// Do work with the results of the 1st step
// in the waterfall.
// Finish the water fall
callback( null, mapData );
}
], function( err, result ) {
if ( err ) {
console.log( err );
return;
}
console.log( result );
});
现在getCoords
存在两个问题。首先是它没有向它的回调返回正确的参数,其次它并不总是使用它的回调。第二个问题是 huge ,因为它会导致程序挂起并中断。
我在功能中评论了2个修复程序。
修正了getCoords:
function getCoords ( callback ) {
var query = new Parse.Query( 'userGeoCoordinates' );
query.exists( 'location' )
query.find( {
success: function ( result ) {
for ( var i = 0; i < result.length; i++ ) {
var object = result[ i ];
var user = {};
user.userId = object.get( 'userId' );
user.coords = [];
if ( !user_dedupe( user.userId ) ) {
all_users.push( user );
}
}
for ( var i = 0; i < all_users.length; i++ ) {
for ( var j = 0; j < result.length; j++ ) {
var object = result [ j ];
if( object.get( 'userId' ) == all_users[ i ].userId ) {
all_users[i].coords.push(
[ object.get( 'location' )._longitude , object.get( 'location' )._latitude ]
);
}
}
}
// This is the original callback, let fix it
// so that it uses the normal return arguments
// callback( all_users );
// Return null for no error, then the resutls
callback( null, all_users );
},
error: function( error ) {
// Here is the second, bigger, issue. If the
// getCoords had an error, nothing the callback
// isn't called. Lets fix this
// console.log( 'error' );
// Return the error, an no results.
callback( error );
}
});
}
修复了getCoords
功能后,您可以简化瀑布:
第一个简化瀑布:
async.waterfall([
function( callback ) {
// getCoords returns the expected results
// so just pass in our callback
getCoords ( callback );
},
function( mapData, callback ) {
// Do work with the results of the 1st step
// in the waterfall.
// Finish the water fall
callback( null, mapData );
}
], function( err, result ) {
if ( err ) {
console.log( err );
return;
}
console.log( result );
});
但async有一个很好的功能。如果您的瀑布步骤只是调用一个返回期望结果的函数,您可以使用async.apply进一步简化它。
第2次简化瀑布:
async.waterfall([
async.apply( getCoords ),
function( mapData, callback ) {
// Do work with the results of the 1st step
// in the waterfall.
// Finish the water fall
callback( null, mapData );
}
], function( err, result ) {
if ( err ) {
console.log( err );
return;
}
console.log( result );
});
答案 1 :(得分:2)
尝试在getCoords
回调中放置瀑布的第一个函数的回调。这样,只有在getCoords
回调设置了mapData
之后才会调用瀑布中的第二个函数,此外,当您调用回调时,mapData
现在将在范围内。
async.waterfall([
function( callback ) { // F1
getCoords ( function( data ) {
mapData = data;
callback(null, mapData); // this is the entry point for F2
});
},
function( mapData, callback ) { // now F2 is invoked only after mapData is set
//getEmail ( mapData );
callback( null, mapData );
}],
function( err, result ) {
console.log( result );
});