Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2012/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript承诺链接-奇怪的行为_Javascript_Es6 Promise - Fatal编程技术网

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。除了他没有。他的所有手动函数都没有正确的错误处理。让经过测试的库来完成这项工作确实更好。