为什么在循环完成之前解析objlist。由于for循环是同步的,我希望在for循环完成后运行,但是正在解析带有空对象的列表。
function myFunction(path,files){
return new Promise(function(resolve,reject){
let objlist=[];
files.forEach(function(file,index){
console.log(file)
objlist[index]={};
fs.stat(path + '\\' + file, function(err,stats){
if(err){
console.log(err.code)
console.log(err)
throw err;
}
if(stats.isDirectory()){
objlist[index].file = 'folder'
}
else if(stats.isFile()){
objlist[index].file = 'file'
}
objlist[index].name = file
console.log(objlist[index].name) //gives correct output
objlist[index].size = stats.size
});
})
console.log(objlist); //gives list of empty objects
resolve(objlist);
});
}
答案 0 :(得分:1)
forEach
需要一个函数并同步执行它(参见JavaScript, Node.js: is Array.forEach asynchronous?)。 fs.stat
是异步的,因此无法保证在调用resolve(objlist)
之前所有迭代都会完成。
这是一个建议:
const objlist = await Promise.all(files.map(async file => {
// return a promise
}))
resolve(objlist)
我喜欢这篇关于promises的文章和ES6的推文:https://developers.google.com/web/fundamentals/primers/promises
的反馈答案 1 :(得分:0)
fs.stat
调用不同步,因为它使用回调。你的forEach
循环将启动所有fs.stat
进程然后继续,但它不会(也不能让它)等待所有回调在它继续之前被调用。
我认为像下面这样的方法会起作用。 fs-extra
是fs
的优秀版本,bluebird
是一个扩展标准Promise的promise库。我不确定是否有必要,你没有说出你正在使用哪个版本的Node;我正在使用它来访问each
方法。尝试没有蓝鸟,它可能会工作。
var fs = require('fs-extra');
var Promise = require('bluebird');
global.Promise = Promise;
function myFunction(path,files){
return Promise
.each(files, function(file) {
return fs
.stat(path + '\\' + file)
.then(function(stats) {
var result = {
name: file,
size: stats.size
};
if ( stats.isDirectory() ) result.file = 'folder';
if ( stats.isFile() ) result.file = 'file'
return Promise.resolve(result);
});
})
.tap(console.log)
.catch(function(err) {
console.log(err.code);
console.log(err);
throw err;
});
}
答案 2 :(得分:0)
如果您不想使用等待,您可以使用Promise.all或计数器来了解所有fs.stat
何时已解决:
仅使用Promise.all
:
function myFunction(path,files){
return Promise.all(files.map(function(file,index){
console.log(file)
var obj = {};
fs.stat(path + '\\' + file, function(err,stats){
if(err){
console.log(err.code)
console.log(err)
throw err;
}
if(stats.isDirectory()){
obj.file = 'folder'
}
else if(stats.isFile()){
obj.file = 'file'
}
obj.name = file
console.log(objlist[index].name) //gives correct output
obj.size = stats.size
return obj;
});
}))
.then(objList => {
console.log(objlist); //gives list of empty objects
resolve(objlist);
});
}
或使用计数器:
function myFunction(path,files){
return new Promise(function(resolve,reject){
let objlist=[];
var counter = files.length;
files.forEach(function(file,index){
console.log(file)
objlist[index]={};
fs.stat(path + '\\' + file, function(err,stats){
counter--;
if(err){
console.log(err.code)
console.log(err)
throw err;
}
if(stats.isDirectory()){
objlist[index].file = 'folder'
}
else if(stats.isFile()){
objlist[index].file = 'file'
}
objlist[index].name = file
console.log(objlist[index].name) //gives correct output
objlist[index].size = stats.size
if(counter == 0) {
console.log(objlist); //gives list of empty objects
resolve(objlist);
}
});
})
});
}