2015-11-19 217 views
0

我遇到過類似的問題,但沒有一個適合我的方案。從forEach回調中修改外部數組變量

在下面的代碼中,我使用dockerode Javascript庫中的listContainers()函數來列出我的Docker容器的ID。該代碼片段從dockerode自述文件中的一個改編而來。 listContainers調用工作,console.log行按預期輸出id。問題是我無法將容器ID推入在函數調用外部聲明的數組中 - 結果是在調用listContainers之後該數組仍然爲空。

我對Javascript並不是非常有經驗,但我認爲這個問題是由於嘗試在回調函數中進行推送。問題是listContainers是異步的,所以這意味着//CONSOLE LOG #2實際上在//CONSOLE LOG #1之前執行。

如何將id值捕獲到函數調用之外的id數組中?

//Here is where I want to store my container ids. 
var ids = []; 

//Here is the dockerode call 
dockerCli.listContainers(function(err, containers) { 

    containers.forEach(function(containerInfo) { 

     //log shows the correct id 
     console.log(containerInfo.Id); 

     //Here I try to save the container id to my array 
     ids.push(containerInfo.Id); 
    }); 

    //CONSOLE LOG #1 Here I can see that the array has the correct values 
    console.log("IDs: "+ids.toString()); 
}); 

//CONSOLE LOG #2 Shows that the array is empty 
console.log("IDs: "+ids.toString()); 
+1

'listContainers'是否產生異步回調? –

+0

嗯,它會對Docker服務器進行外部調用,所以是的,我認爲是這樣。我需要使用Javascript承諾嗎? – EkcenierK

+1

這可能是一種使用它的方法,是的。看到[這個問題](http://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-asynchronous-call) - 這個問題的措辭是略有不同的(因爲它是試圖從函數返回而不是內聯回調),但前提是相同的。 –

回答

1

與其他評論者的幫助下,我意識到listContainers調用是異步的,根本就沒有辦法從中返回一個值。

那麼如何初始化和使用我的ids數組?我創建了自己的函數,它包裝了dockerode listContainers調用。這個函數然後用自己的回調函數來處理ids數組。這使我可以在自己的回調中訪問初始化的ids數組,從處理ids數組的功能中分離出獲取容器列表的功能。

ids = []; 

//Define my function that takes a callback function 
//and just fetch the container ids 
function getContainerJsonFromDocker(callback) { 

    dockerCli.listContainers(function(err, containers) { 

     containers.forEach(function(containerInfo) { 
      console.log(containerInfo.Id); 
      ids.push(containerInfo.Id); 
     }); 
     return callback(ids); 
    }); 
} 

//Now call my function, and pass it an anonymous callback 
//The callback does the processing of the ids array 
getContainerJsonFromDocker(function(ids) { 

    //This shows the array is initialised :) 
    console.log("IDs: " + ids.toString()); 

    //Write my array to .json file 
    var outputFilename = 'data.json'; 
    fs.writeFile(outputFilename, JSON.stringify(ids, null, 4), 
      function(err) { 
       if (err) { 
        console.log(err); 
       } else { 
        console.log("JSON saved to " + outputFilename); 
       } 
      }); 
}); 
0

你不需要傳遞全局變量ID與回調一起試試這個,

//Here is where I want to store my container ids. 
var ids = []; 

//Here is the dockerode call 
dockerCli.listContainers(function(err, containers) { 

    containers.forEach(function(containerInfo) { 

     //log shows the correct id 
     console.log(containerInfo.Id); 

     //Here I try to save the container id to my array 
     ids.push(containerInfo.Id); 
    }); 
}); 

//Shows that the array is empty 
console.log("IDs: "+ids.toString()); 
+0

如果我不通過變量,結果仍然是相同的。問題是別的,與範圍內的回調 – EkcenierK

+0

你試過把你的控制檯放在'listContainers'回調函數裏面嗎? – azad

+0

是的,'console.log(「IDs:」+ ids.toString());'如果我把它放在'forEach'之外,但在'listContainers'函數內,問題是'listContainers'是異步的,所以直到我的其他代碼執行完畢纔會調用它。我會更新我的問題。 – EkcenierK