函数返回承诺对象而不是实际数据。

时间:2022-06-10 15:27:33

Following this snippet I am trying to write a function that loops trough a directory, finds directories, and reads xml file names from those directories (I know that the folder structure will always remain the same). So far my function is working as expected, but when I try to get the return from the function I just get Promise objects.

在这段代码之后,我尝试编写一个函数来循环目录、查找目录并从这些目录中读取xml文件名(我知道文件夹结构始终保持不变)。到目前为止,我的函数运行正常,但当我试图从函数中获得返回值时,我得到的只是承诺对象。

My code:

我的代码:

const Promise = require('bluebird');
const fs = Promise.promisifyAll(require('fs'));
const path = require('path');

function getFileNames(rootPath) {
  // Read content of path
  return fs.readdirAsync(rootPath)
    // For every file in path
    .then(function(directories) {
      // Filter out the directories
      return directories.filter(function(file) {
        return fs.statSync(path.join(rootPath, file)).isDirectory();
      });
    })
    // For every directory
    .then(function(directories) {
      return directories.map(function(directory) {
        // Read file in the directory
        return fs.readdirAsync(path.join(rootPath, directory))
          .filter(function(file) {
            return path.extname(file) == '.XML';
          })
          .then(function(files) {
            // Do something with the files
            return files;
          });
        });
    });
}

getFileNames('./XML').then(function(files) {
  console.log(files);
});

When I console.log(files) inside the last .then function inside getFileNames, I get the actual arrays of file names in the console. But when I run the code above I get this output:

当我在last .log(文件)中,然后在getFileNames中运行时,我得到了控制台中的文件名称的实际数组。但是当我运行上面的代码时,我得到这个输出:

[ Promise {
    _bitField: 0,
    _fulfillmentHandler0: undefined,
    _rejectionHandler0: undefined,
    _promise0: undefined,
    _receiver0: undefined },
  Promise {
    _bitField: 0,
    _fulfillmentHandler0: undefined,
    _rejectionHandler0: undefined,
    _promise0: undefined,
    _receiver0: undefined },
  Promise {
    _bitField: 0,
    _fulfillmentHandler0: undefined,
    _rejectionHandler0: undefined,
    _promise0: undefined,
    _receiver0: undefined },
  Promise {
    _bitField: 0,
    _fulfillmentHandler0: undefined,
    _rejectionHandler0: undefined,
    _promise0: undefined,
    _receiver0: undefined },
  Promise {
    _bitField: 0,
    _fulfillmentHandler0: undefined,
    _rejectionHandler0: undefined,
    _promise0: undefined,
    _receiver0: undefined } ]

Why is this happening and how to fix it?

为什么会发生这种情况,以及如何修复它?

4 个解决方案

#1


2  

In the lines

的行

.then(function(directories) {
  return directories.map(function(directory) {
    return fs.readdirAsync…

you are creating a promise for an array of promises, and that's exactly what you're getting in your final log. Instead of returning an array of promises, you need to return a promise for an array of values - and Promise.all is exactly what does that:

您正在为一系列的承诺创建一个承诺,这正是您在最终日志中得到的。您需要返回一个承诺数组,而不是返回一个承诺数组的值和承诺。一切都是这样:

.then(function(directories) {
  return Promise.all(directories.map(function(directory) {
    return fs.readdirAsync(…)
    …
  }));
})

However, in Bluebird it would be more idiomatic to use Promise.map(directories, function(…) { … }) or even the map method (similar to how you already used .filter did on the files in each directory):

然而,在蓝鸟中,使用承诺更符合习惯。映射(目录、函数(…){…})甚至映射方法(类似于您已经在每个目录中的文件上使用.filter):

function getFileNames(rootPath) {
  return fs.readdirAsync(rootPath)
  .filter(function(file) {
    return fs.statAsync(path.join(rootPath, file)).then(function(s) {
      return s.isDirectory();
    });
  })
  .map(function(directory) {
//^^^^
    return fs.readdirAsync(path.join(rootPath, directory))
    .filter(function(file) {
      return path.extname(file) == '.XML';
    })
    .map(function(file) {
      // Do something with every file
      return file;
    });
  });
}

#2


0  

try this

试试这个

return getFileNames('./XML').then(function(files) {
    console.log(files);
    return files;
});

#3


0  

This piece of code:

这段代码:

.then(function(directories) {
   return directories.map(function(directory) {
     return fs.readdirAsync(path.join(rootPath, directory))
     ...

will return an array of promises to the then callback. An array of promises count as an immediate value here, will not be coerected to a Promise of an array. To convert an array of promises to a promise of an array you could use Promise.all, but since you are using bluebird, you have a better option:

将向当时的回调返回一个承诺数组。一个承诺数组在这里作为一个即时值,不会被强制为一个承诺数组。要将一个承诺数组转换为一个承诺数组,你可以使用promise。所有,但既然你在使用蓝鸟,你有一个更好的选择:

All you have to do is to use Promise.map:

你所要做的就是使用承诺。

.then(function(directories) {
   return Promise.map(directories, function(directory) {
     return fs.readdirAsync(path.join(rootPath, directory))
     ...

#4


0  

Figured it out, there was one .then too much on the second function:

算出来了,有一个。

const Promise = require('bluebird');
const fs = Promise.promisifyAll(require('fs'));
const path = require('path');

function getFileNames(rootPath) {
  // Read content of path
  return fs.readdirAsync(rootPath)
      .then(function(content) {
        return content.filter(function(file) {
          return fs.statSync(path.join(rootPath, file)).isDirectory();
        });
      })
      // For every directory
      .map(function(directory) {
        // Read files in the directory
        return fs.readdirAsync(path.join(rootPath, directory))
            .filter(function(file) {
              return path.extname(file) == '.XML';
            });
      });
}

getFileNames('./XML').then(function(files) {
  console.log(files);
});

#1


2  

In the lines

的行

.then(function(directories) {
  return directories.map(function(directory) {
    return fs.readdirAsync…

you are creating a promise for an array of promises, and that's exactly what you're getting in your final log. Instead of returning an array of promises, you need to return a promise for an array of values - and Promise.all is exactly what does that:

您正在为一系列的承诺创建一个承诺,这正是您在最终日志中得到的。您需要返回一个承诺数组,而不是返回一个承诺数组的值和承诺。一切都是这样:

.then(function(directories) {
  return Promise.all(directories.map(function(directory) {
    return fs.readdirAsync(…)
    …
  }));
})

However, in Bluebird it would be more idiomatic to use Promise.map(directories, function(…) { … }) or even the map method (similar to how you already used .filter did on the files in each directory):

然而,在蓝鸟中,使用承诺更符合习惯。映射(目录、函数(…){…})甚至映射方法(类似于您已经在每个目录中的文件上使用.filter):

function getFileNames(rootPath) {
  return fs.readdirAsync(rootPath)
  .filter(function(file) {
    return fs.statAsync(path.join(rootPath, file)).then(function(s) {
      return s.isDirectory();
    });
  })
  .map(function(directory) {
//^^^^
    return fs.readdirAsync(path.join(rootPath, directory))
    .filter(function(file) {
      return path.extname(file) == '.XML';
    })
    .map(function(file) {
      // Do something with every file
      return file;
    });
  });
}

#2


0  

try this

试试这个

return getFileNames('./XML').then(function(files) {
    console.log(files);
    return files;
});

#3


0  

This piece of code:

这段代码:

.then(function(directories) {
   return directories.map(function(directory) {
     return fs.readdirAsync(path.join(rootPath, directory))
     ...

will return an array of promises to the then callback. An array of promises count as an immediate value here, will not be coerected to a Promise of an array. To convert an array of promises to a promise of an array you could use Promise.all, but since you are using bluebird, you have a better option:

将向当时的回调返回一个承诺数组。一个承诺数组在这里作为一个即时值,不会被强制为一个承诺数组。要将一个承诺数组转换为一个承诺数组,你可以使用promise。所有,但既然你在使用蓝鸟,你有一个更好的选择:

All you have to do is to use Promise.map:

你所要做的就是使用承诺。

.then(function(directories) {
   return Promise.map(directories, function(directory) {
     return fs.readdirAsync(path.join(rootPath, directory))
     ...

#4


0  

Figured it out, there was one .then too much on the second function:

算出来了,有一个。

const Promise = require('bluebird');
const fs = Promise.promisifyAll(require('fs'));
const path = require('path');

function getFileNames(rootPath) {
  // Read content of path
  return fs.readdirAsync(rootPath)
      .then(function(content) {
        return content.filter(function(file) {
          return fs.statSync(path.join(rootPath, file)).isDirectory();
        });
      })
      // For every directory
      .map(function(directory) {
        // Read files in the directory
        return fs.readdirAsync(path.join(rootPath, directory))
            .filter(function(file) {
              return path.extname(file) == '.XML';
            });
      });
}

getFileNames('./XML').then(function(files) {
  console.log(files);
});