2016-07-06 58 views
0

我目前正在學習如何使用NodeJS並編寫這個相對簡單的函數以固定的時間間隔運行。此功能的目的是檢索新創建的Droplet並更新其IP地址。NodeJS數組意外的行爲

router.newDroplets = setInterval(function() { 

    Server.find().then(function(svrs) { 
     for (var i = 0; i < svrs.length; i++) { 
      if (svrs[i].status == "Creating") { 
       library.getDropletById(svrs[i].serverid).then(function(svr) { 
        if (svr.droplet) { 
         for (var j = 0; j < svr.droplet.networks.v4.length; j++) { 
          if(svr.droplet.networks.v4[j].type == 'public') { 
           var ip_address = svr.droplet.networks.v4[j].ip_address; 
           console.log(ip_address); 

           Server.update({serverid: svr.droplet.id}, {ipaddress: ip_address, status: "Online"}, function(error, n) { 
            if (error) console.log(error); 
            else console.log(n); 
           }); 
          } 
         } 
        } else if (svr.id) { 
         // NOTE THIS LINE 
         console.log(svrs); 
        } 

       }, function() { 

       }); 
      } 
     } 
    }, function() { 

    }); 

}, 2500); 

特有的行爲是與上面標記的行。

當我使用console.log(svrs)時,我在MongoDB的Server集合中獲得了一組JSON文檔。但是,當我使用console.log(svrs[i])時,控制檯中會記錄undefined。即使我在for循環之外聲明var i = 0;,也會發生這種情況。爲什麼會發生這種情況,我如何才能訪問svrs[i]

+0

'這是即使我聲明我變種= 0;在for循環之外,哪個for循環? –

+0

正確使用承諾,並避免編寫這樣的意大利麪代碼(嵌套承諾)。 – undefined

+0

你有沒有試過登錄'我'? –

回答

2

承諾的工作方式是承諾鏈異步運行。在代碼運行時,i等於svrs.length,因此svrs[i]將爲undefined。這是因爲在調用任何then回調之前,for循環將全部執行。你可以轉換你的代碼中使用Array.prototype.forEach

所以,你可以嘗試這樣

svrs.forEach(function(svrInstance, i) { 
    if (svrInstance.status == "Creating") { 
    library.getDropletById(svrInstance.serverid).then(function(svr) { 
     if (svr.droplet) { 
     ... 
     } else if (svr.id) { 
     console.log(svrs[i]); 
     } 
    }); 
    } 
}); 
+0

非常感謝您的解釋和建議。我從來不知道只有在for循環完成循環後才調用'then'回調函數。 –