2014-03-29 96 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); 
    });