关于 Node.js promise 中的局部变量

About the local variable in Node.js promise

我是Node.js.I的新人,定义了一个数组作为局部变量,想在后面使用然后,我把一些有用的数据保存在it.But最后,数组是empty.Can谁告诉我为什么?谢谢你的支持。

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);
});

您可以使用 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               
 })

问题是您 videoId2URL 显示得太早了。

Device.findOne returns 异步执行的承诺。但是 Video.findOne 也是 returns 异步执行的承诺。

因此,当您执行 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);
});

当您执行 console.log(videoId2URL) 时,您仍在脚本的主堆栈中,而 none 的 push 回调已被执行。

你可以用一个数组来收集Video.findOne返回的promise,最后用Promise.all把所有的promises抽干然后做日志。

顺便说一句,2 return 中的 none 是必需的,您可以安全地删除它们。 第一个未使用,因为它在 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);
    });
});