2016-05-23 68 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); 
    }); 

} 

我希望澄清的东西小。