Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/407.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_Promise - Fatal编程技术网

Javascript 为什么承诺先解决?

Javascript 为什么承诺先解决?,javascript,promise,Javascript,Promise,根据stackoverflow上的代码片段,我想读取目录中的所有文件,然后继续。 我加了一个承诺,但不知怎么的,这不起作用 我的目录包含2个文件,控制台日志输出为: 承诺已解决 内部文件名 内部文件名 内部读取文件 内部读取文件 function readFiles(dirname, onFileContent, onError) { return new Promise((resolve, reject) => { fs.readdir(dirname, func

根据stackoverflow上的代码片段,我想读取目录中的所有文件,然后继续。 我加了一个承诺,但不知怎么的,这不起作用

我的目录包含2个文件,控制台日志输出为:
承诺已解决
内部文件名
内部文件名
内部读取文件
内部读取文件

function readFiles(dirname, onFileContent, onError) {
    return new Promise((resolve, reject) => {
        fs.readdir(dirname, function(err, filenames) {
            filenames.forEach(function(filename) {

                console.log('inside filenames');

                fs.readFile(dirname + filename, 'utf-8', function(err, content) {
                    onFileContent(filename, content);
                });
            });
        });
    });
}

var data = [];
readFiles('datadir/', function(filename, content) {
    console.log('inside readFiles');
    data.push(filename);
}).then(
    console.log('promise resolved');
    //proceed handling the data-array
);
承诺不是“先解决”。对
console.log
的调用在读取第一个文件之前执行

你永远不会按照你的承诺打电话给
resolve
,所以
然后
就永远不会被打电话了。但是,您正在将
console.log的结果传递给
然后
console.log
的结果无效

您可以通过更正问题来测试这一点:

readFiles('datadir/', function(filename, content) {
    console.log('inside readFiles');
    data.push(filename);
}).then(function(){ // NOTE: addition of function(){..}
    console.log('promise resolved');
    //proceed handling the data-array
});
您会注意到消息从未写入控制台


这就是问题所在——如何修复它。在node中完全基于异步/承诺的代码需要一些思考

我假设您希望在解决您的承诺之前,等待所有文件的内容被读取。这有点棘手,因为您有两个异步调用(读取文件列表,然后分别读取其内容)。将文件的读取封装到自己的承诺中可能更容易。大概是这样的:

function readFile(filePath){
    return new Promise((resolve,reject) => {
       fs.readFile(filePath, "utf-8", function(err,content) => {
           if(err) reject(err)
           else resolve({path:filePath, content:content})
        });
    });
}
readdir
执行相同操作,以使其也可链接:

function readDirectory(dir){
    return new Promise((resolve,reject) => {
       fs.readdir(dirname, function(err, filenames) {
          if(err) reject(err);
          else{
             resolve(filenames.map(fn => dir + fn));
          }
      });
    });
}
这样做的原因是,您可以使用
Promise.all
来等待所有文件内容

function readFileContents(dirname) {
    return readDirectory(dirname)
            .then(files => 
                 Promise.all(files.map(file => readFile(file))
             );
}
用法:

readFileContents('datadir/').then(files => {
    files.forEach(file => {
        console.log(file.path, file.content.length);
    });
});

您的代码甚至不会用分号执行,但看起来您应该有
then(function(){
而你只有
然后
。假设你的真实代码中没有分号,这就是解释。我看不出你承诺的意义-你永远都不会
解决它,你使用回调来获取文件内容。@Jamiec承诺的意义是等到所有文件都被读取。我明白了,但你是从来没有这样做过。你想让这个承诺成为正确的基础吗?是的,我不知道该把决心放在哪里(),不能把我的头缠绕在它周围。避免使用in
readFiles
!你应该使用promise构造函数创建一个
readDir
函数,然后将它与
readFile
正确地结合到
readFiles
@Bergi中-我想这就是我用
readFile
方法所做的。你能解释一下你的意思吗“使用承诺构造函数”?我写的两个方法只是简单的
promise
包装了一个没有承诺接口的api调用。我看不出有什么危害,但可能我误解了。问题是它不仅包装了api调用,而且还包装了
promise.all(…)
东西(而且确实处理错了)。你应该像对待
readFile
一样,在
fs.readdir
调用帮助函数时,考虑到promise包装器。
promise。所有(…)
都需要放入
。然后(…)
回调。@jamice谢谢,太好了!