关于 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);
});
});
我是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);
});
});