2016-05-23 74 views
-1

我訪問API Trello的,但我碰到下面的問題就來了:陣列返回undefined,因爲異步

Trello訪問這些信息,讓每個現有行的id,代碼如下:

var x; 
var numberCardsByList = []; 

trello.get("/1/boards/[idBoard]/lists/all", function(err, data) { 
    if (err) throw err; 
    console.log("Number of list: " + data.length); 

    for(var i=0; i<data.length; i++){ 
     x = data[i]; 
     findNumberCards(x); 
    } 
}); 

正如你所看到的,在獲得大小之後,我用循環遍歷所有這些隊列,在循環內將每行連接到一個變量x中,並調用一個函數來獲取隊列中的卡片數量。對於卡的數量的代碼如下:

function findNumberCards(x){ 
    trello.get("/1/lists/"+x.id+"/cards", function(err, dados){ 
     if(err) throw err; 
     console.log("Name List: " + x.name + " have " + dados.length + " cards"); 
     numberCardsByList[x.name] = dados.length; 
    }); 
} 

在此之前的所有權利,但是當我嘗試在Trello搜索結束後訪問向量numberCardsByList,它返回undefined:

var x; 
var numberCardsByList = []; 

trello.get("/1/boards/[idBoard]/lists/all", function(err, data) { 
    if (err) throw err; 
    console.log("Quantidade de Filas: " + data.length); 

    for(var i=0; i<data.length; i++){ 
     x = data[i]; 
     findNumberCards(x); 
    } 
}); 
console.log(numberCardsByList); 

我知道,這是因爲異步,但是,不能解決。

+0

請以更完整的方式展示您的代碼示例..我認爲發生的事情是您首先調用'/ 1/boards/[idBoard]/lists/all',然後在回調函數中調用另一個函數做異步操作,並且在那個函數之後,如果我錯了,你還要做其他的事情糾正我 –

+0

yes是正確的,因爲我解決了這個問題? – Jonathan

回答

0

您面臨的問題已經解決了很多次。如果您想了解更多信息,請搜索關鍵字「Promise」。如果你熟悉的jQuery,嘗試查找:$.whenAll$.ajax().done$.ajax().always

如果你想拿出一個輕重量的溶液自己,這裏有一個指針:

到時候你到達您的console.log(numberCardsByList),您的請求由findNumberCards觸發尚未完成,使Array爲空。您需要確保知道何時所有findNumberCards請求已完成,然後然後將它們記錄下來。或者,您可以在每次完成時將它們記錄到

大致有兩種方法:

  1. 您打開請求的跟蹤和調用一個函數時,請求處理。
  2. 觀察你numberCardsByList對象,然後調用一個函數,只要加入項目(你不會知道,如果他們加入異步或同步)

我建議用第一種方法去。看看這個示例代碼和註釋:

var numberCardsByList = {}; 
 

 
// This array will store the url for every open request 
 
var openRequests = []; 
 

 
var removeRequest = function(url) { 
 
    var index = openRequests.indexOf(url); 
 
    if (index === -1) return; 
 

 
    // Remove url from array 
 
    openRequests = openRequests 
 
    .slice(0, index) 
 
    .concat(openRequests 
 
     .slice(index + 1)); 
 
}; 
 

 
// This will be called whenever one request completes 
 
var onComplete = function(url) { 
 
    removeRequest(url); 
 
    
 
    // When all have completed, we can call our callback 
 
    if (openRequests.length === 0) { 
 
    onAllComplete(); 
 
    } 
 

 
}); 
 

 
// This will be called when there are no open requests left 
 
var onAllComplete = function(data) { 
 
    console.log(numberCardsByList); 
 
} 
 

 

 
trello.get("/1/boards/[idBoard]/lists/all", function(err, data) { 
 
    if (err) throw err; 
 
    console.log("Number of list: " + data.length); 
 

 
    for (var i = 0; i < data.length; i++) { 
 
    x = data[i]; 
 
    findNumberCards(x); 
 
    } 
 
}); 
 

 

 
function findNumberCards(x) { 
 
    var url = "/1/lists/" + x.id + "/cards"; 
 
    
 
    // Before we make the request, we register it: 
 
    openRequests.push(url); 
 

 
    trello.get(url, function(err, dados) { 
 
    numberCardsByList[x.name] = dados.length; 
 
    
 
    // When it is completed, we call onComplete 
 
    onComplete(url); 
 
    }); 
 
};

注意,這onAllComplete也不是100%安全的:如果下一個開始前的請求完成它可能被多次調用。

結論:

如果可以的話,我會使用一個庫來處理的承諾。如果你想嘗試自己創建一些東西,你可以嘗試跟蹤請求並在完成時執行回調。

+0

謝謝。有效 – Jonathan

0

請記住我的上面的代碼最有可能不會爲你工作,因爲我不知道你的代碼是怎麼回事,所以這是一個例子/解釋如何處理你的問題。

由於您不熟悉異步操作,我會假設您沒有預先承諾的知識,因此會給您一個不太理想的解決方案 - 但承諾會更好,您應該明確地瞭解它們。

您需要在異步代碼的結果中執行順序過程。

首先,您將創建例如第二操作的功能:

function numberCardsByList (param1,param2){.....} 

然後,您將更改fineNumberCards也接受回調:

function findNumberCards(x, callback){ 
    trello.get("/1/lists/"+x.id+"/cards", function(err, dados){ 
     if(err) throw err; 
     console.log("Name List: " + x.name + " have " + dados.length + " cards"); 
     numberCardsByList[x.name] = dados.length; 
    }); 

    // pass in any params you need. 
    callback(); 
} 

然後你會通過新創建功能numberCardsByListfindNumberCards或任何你想要的地方。 trello.get(「/ 1/boards/[idBoard]/lists/all」,函數(err,data)如果(錯誤)拋出err; console.log(「Number of list:」+ data.length );

for(var i=0; i<data.length; i++){ 
     x = data[i]; 
     // and here we are calling findNumberCards and passing in the callback.. 
     findNumberCards(x, numberCardsByList); 
    } 
}); 

這通常是你將如何處理異步操作,你會傳遞一個回調要執行的下一個操作

更新

這裏是如何的例子這是通過另一個場景來完成的,只是爲了展示更遠的點

我們開始通過獲取用戶

service.getUser(userName, function(err,user){ 
    if(user) { 
    // we get user picture passing getPictureSize as callback 
    getUserPicture(user.picture, getPictureSize) 
    } 
}) 

我們得到的pictureURL

function getUserPicture(picName, cb){ 
    service.getPictureURL(picName, function(err, pictureURL){ 
    if(pictureURL) { 
     // we then call the callback - the next async operation we want. 
     cb(pictureURL); 
    } 
    }); 
} 

我們得到的圖片尺寸 - 這是最後一個操作

function getPictureSize(pictureURL){ 
    service.getPictureSize(pictureURL, function(err, pictureSize){ 
    $('.picName').attr('src', picName); 
    $('.picName').width(pictureSize.width); 
    $('.picName').height(pictureSize.height); 
    }); 

} 

我希望澄清的東西小。