Javascript承诺链接-奇怪的行为
我正在使用以下代码进行测试:Javascript承诺链接-奇怪的行为,javascript,es6-promise,Javascript,Es6 Promise,我正在使用以下代码进行测试: var http = require('http'); var fs = require('fs'); function getFullPath(file){ return new Promise(function(resolve, reject){ fs.realpath(file, function(err, path){ resolve(path); }); }); } functio
var http = require('http');
var fs = require('fs');
function getFullPath(file){
return new Promise(function(resolve, reject){
fs.realpath(file, function(err, path){
resolve(path);
});
});
}
function getFileSize(file){
return new Promise(function(resolve, reject){
fs.stat(file, function(err, stats){
resolve(stats.size);
});
});
}
function calculateSize(files){
var size = 0;
var files_count = files.length-1;
return new Promise(function(resolve, reject){
files.forEach(function(file, i){
getFullPath(file).then(getFileSize).then(function(tempSize){
size += tempSize;
console.log(file, tempSize);
if(files_count == i){
resolve(size);
}
});
});
});
}
function getFiles(path){
console.warn('Staring path:',path);
return new Promise(function(resolve, reject){
fs.readdir(path, function(err, files){
if(err || !files){
reject(err);
} else {
resolve(files);
}
});
});
}
getFiles('/home/galio/DEV/js-sandbox').then(function(result){
return calculateSize(result);
}, function(err){
console.log('ERROR:', err);
}).then(function(size){
console.log('All files size is: ', size);
});
我使用节点v 6.9.1运行它,结果是:
.eslintrc.json 528
.git 4096
.gitignore 26
README 0
callbacks.js 1402
functions-1.js 530
functions-2.js 564
functions-3.js 1798
functions-4.js 737
functions-5.js 1045
All files size is: 10726
到目前为止,一切顺利。但有时,我可能会跑10次中的1次:
.eslintrc.json 528
.git 4096
.gitignore 26
README 0
functions-1.js 530
callbacks.js 1402
functions-2.js 564
functions-3.js 1798
functions-5.js 1045
All files size is: 9989
functions-4.js 737
请注意,有时最终结果是如何在实际循环完成之前执行的。为什么?我自己无法解决这个问题,我需要帮助认识到是什么导致了这个错误
另外,位于底部的文件不是functions-4.js
请提供帮助如果您只想在文件的所有计算完成后进行解析,您可能应该在函数中使用
计算大小(文件)
function calculateSize(files) {
return Promise.all(files.map(function (file) {
return getFullPath(file).then(getFileSize).then(function(size) {
console.log(file, size)
return size
})
})
}).then(function (sizes) {
return sizes.reduce(function (a, b) {
return a + b
})
})
}
您甚至可以通过删除最后的
然后
回调,使函数将一个文件数组映射到一个大小数组。我认为您的第二个然后
没有等待calculateSize()
试试这个
getFiles('/home/galio/DEV/js-sandbox').then(function(result){
calculateSize(result).then(function(size){
console.log('All files size is: ', size);
}
},
function(err){ console.log('ERROR:', err); }
);
我建议不要滚动你自己的承诺,这是乏味和容易出错的。让像这样的图书馆为你做这件事 与bluebird提供的其他功能(如
.map()
和.reduce()
的实现)一起,您的代码可以变得简单明了,如下所示:
var Promise = require('bluebird');
var path = require('path');
var fs = Promise.promisifyAll(require('fs'));
function calculateSizeAsync(dir) {
return fs.readdirAsync(dir)
.map(file => path.join(dir, file))
.map(filepath => fs.statAsync(filepath))
.reduce((total, stats) => {return total + stats.size}, 0);
}
calculateSizeAsync('/home/galio/DEV/js-sandbox')
.then(totalSize => console.log('All files size is: ' + totalSize))
.catch(err => console.error('ERROR:', err));
不太确定我是否理解正确。但是
calculateSize
是否应该返回一个承诺数组,每个文件一个?或者,您需要在该方法中处理不同的循环。我很确定在这个循环中有一个竞赛条件。我个人可能会返回一系列承诺,每个文件一个。编辑:另一方面,我会使用arrow函数,因为您已经使用了ES6()“if(files_count==I)”是否已经阻止了承诺的实现,直到所有的文件都被求和?它可能会阻止,但这种逻辑对我来说似乎很混乱,混乱的代码往往会产生微妙的错误。我更愿意向OP展示如何使用Array#map
和Promise#all
以降低复杂性的方式实现相同的功能。肯定解决了这个问题。非常感谢。我将不得不深入研究Promise.all和Array.map。除了他没有。他的所有手动函数都没有正确的错误处理。让经过测试的库来完成这项工作确实更好。