2017-09-01 157 views
0

我是一個較新的Node.js.I定義了一個數組作爲局部變量,並且想在下面的中使用它,我在其中保存了一些有用的數據。但最後,陣列是空的。有人告訴我爲什麼?感謝您的支持。關於Node.js中的局部變量promise

const Device = require("./mongo.js").Device; 
const Video = require("./mongo.js").Video; 

Device.findOne({id:"11112222"}).exec() 
    .then(function(data){ 
    var videoIds = data.videoIds.split(","); 
    var videoId2URL = []; 
    console.log(videoIds); 
    videoIds.forEach(function(one){ 
      return Video.findOne({id:one}).exec() 
      .then(function(data){ 
       videoId2URL.push({id:one,url:data.url}); 
       return videoId2URL; 
      }) 

    }); 
    console.log(videoId2URL); 
}); 
+2

這裏的主要問題是,你syncronous和asyncronous呼叫混合一起沒有適當處理後。特別是當你使用'Promise'時,你正在使用異步代碼,因此你需要改變代碼流。基本上你在'forEach'迭代器中觸發了多個Promise,但是在解析之前打印('console.log')。 – MarcoL

回答

0

的問題是,你是太早顯示videoId2URL

Device.findOne返回一個異步執行的承諾。但Video.findOne也返回一個異步執行的承諾。

所以,當你做console.log(videoId2URL);,由Video.findOne創建的承諾尚未執行。所以你的數組是空的。

您必須等待所有承諾的結束。你可以使用Promise.all

Promise.all(videoIds.map(function(one){ 
     return Video.findOne({id:one}).exec() 

     .then(function(data){ 
      videoId2URL.push({id:one,url:data.url}); 
      return videoId2URL; 
     }); 
}) 

.then(function() { 
    console.log(videoId2URL); 
}); 
+0

爲什麼使用map而不是foreach,我測試了一下,使用map的時候代碼可以運行但是使用foreach的時候失敗了。謝謝。 –

+0

'forEach'什麼都不返回。如果你想將一個數組映射到一個新的數組中,你必須使用'map' – Magus

0

您可以使用Promise.all來解決您的問題。您forEach代碼包含異步代碼。您的最後一行不會等待所有承諾解決。

嘗試用:

var arr = []; 

videoIds.forEach(function(one){ 
      return arr.push(Video.findOne({id:one}).exec()); 
    }); 

Promise.all(arr) // here we are waiting for all async tasks to get resolved 
.then(function(data){ 
     console.log(data); 
     // parse your data here and find array of videoId2URL    
}) 
0

當你做console.log(videoId2URL),你仍然在爲劇本的主棧,而沒有push回調已被執行。

您可以使用數組來收集Video.findOne返回的承諾,最後使用Promise.all排除所有承諾,然後執行日誌記錄。

順便說一句,2 return是沒有必要的,你可以安全地刪除它們。 第一個不使用,因爲它在forEach的同步回調中​​。 第二個不使用,因爲你依靠副作用,而不是使用已解決的值。

嘗試:

const Device = require("./mongo.js").Device; 
 
const Video = require("./mongo.js").Video; 
 

 
Device.findOne({id:"11112222"}).exec() 
 
    .then(function(data){ 
 
    var videoIds = data.videoIds.split(","); 
 
    var videoId2URL = []; 
 
    var promiseArr = []; 
 
    console.log(videoIds); 
 
    videoIds.forEach(function(one){ 
 
     var p = Video.findOne({id:one}).exec() 
 
     .then(function(data){ 
 
     videoId2URL.push({id:one,url:data.url}); 
 
     }); 
 
     promiseArr.push(p); 
 
    }); 
 

 
    Promise.all(promiseArr).then(function() { 
 
     console.log(videoId2URL); 
 
    }); 
 
});