2014-03-29 72 views
5

免责声明:非工程师,很新的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)发生在返回之前,导致一个空的结果。

如何组织这使得getCoords回报mapData之前进行下一块?我可能错过了一些超级明显的东西,谢谢!

+0

这是你正在做的,如果是这样,为什么你甚至需要异步,只需将'getCoords'回调里面的'getEmail'功能? – adeneo

+0

@adeneo这可能只是philsometypaway需要实现连续传递样式的较大实现的一小部分。 –

+0

@JasonAller是正确的 - 我将需要链接在一起的一堆。感谢您的帮助! – philsometypaway

回答

8

回调的乐趣...您需要了解如何使用回调时程序流程的工作原理。这可以用一个非常简单的例子来看。

例子:

function doWork(callback) { 
    console.log(2); 
    setTimeout(callback, 1000); 
} 

function master() { 
    console.log(1); 

    doWork(function() { 
    console.log(3); 
    }); 

    console.log(4); 
} 
master(); 

预期的结果将在propper顺序1,2,3,4控制台日志,但运行的例子,当你看到一些奇怪的日志是乱序1,2,4,3。这是因为3日志记录发生在doWork完成后,而4日志记录在启动doWork后发生,而不是等待它完成。

异步:

你可以做很多与异步库,但是要记住重要的是,回调函数总是收到错误作为第一个参数后面的参数你想传递给列表中的下一个函数。

您链接的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两个问题。首先,它不会将正确的参数返回给它的回调,其次它并不总是使用它的回调。第二个问题是巨大的,因为它会导致您的程序挂起并中断。

我已经在函数中修改了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功能:

1简体瀑布:

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.apply进一步简化它。

2ST简体瀑布:

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); 
}); 
+0

嗨,我是新的JavaScript中的一个,我想问一个问题,在你的例子中你称之为callback(null,mapData);或者说每个人在我看到async.waterfall的末尾使用callback()。我想知道回调函数的用途以及定义的位置 – rahul

+0

@rahul - 将回调函数定义为瀑布的一部分。它作为数组中每个函数的最后一个参数传递。当你调用这个函数时,它基本上是调用数组中的下一个函数。 – Justin808

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); 
    });