提问者:小点点

Promise then()方法没有像预期的那样激发?[副本]


在下面的代码中,我希望之前触发。我猜我在某些地方没有正确使用

我很确定这一行:

  const things = await fs.promises.readdir(folder);

还有这一行

  const stats = await fs.promises.stat(path);

是正确的,因为我们正在等待文件系统的响应。

到目前为止,我还没有遇到错误检查或跨平台代码的问题,只是得到了正确工作的承诺

// Libraries
const fs = require('fs');

// API
getThings('_t/').then(() => {
  console.log('mark-2')
})

// Accesses the file system and returns an array of files / folders
async function getThings (folder) {
  const things = await fs.promises.readdir(folder);
  things.forEach(async (thing)=>{
    await getStats(thing, folder);
  });
}

// Gets statistics for each file/folder
async function getStats (thing, folder) {
  const path = folder + thing;
  const stats = await fs.promises.stat(path);
  console.log('mark-1');
}

共1个答案

匿名用户

问题是您在调用中使用了,而这并不像您所期望的那样工作。

方法实际上并不关心回调函数的返回值(在本例中是承诺returns)。

您应该将数组用于承诺,并使用:

async function getThings (folder) {
  const things = await fs.promises.readdir(folder);
  const promises = things.map(thing =>  getStats(thing, folder));
  return await Promise.all(promises);
}

请注意,这将“并行”地执行承诺,而不是按顺序执行。

如果您想一个接一个地安全地执行承诺,您可以“减少”承诺数组,或者使用常规循环(codefor/code>,

编辑:

让我来解释一下为什么在forEach中使用异步回调函数不起作用。

在最初的示例中,我们有这样的内容:

// ...
things.forEach(async (thing)=>{
  await getStats(thing, folder);
});
// ...

如果我们将回调与分开,则会得到:

const callback = async (thing)=>{
    await getStats(thing, folder);
};

things.forEach(callback);

如果我们对异步函数进行“脱糖”:

const callback = function (thing) {
  return new Promise((resolve, reject) => {
    try {
      getStats(thing, folder).then(stat => /*do nothing*/);
    } catch (err) {
      reject(err);
    }
    resolve();
  });
};

things.forEach(callback);

标记函数可确保函数将始终返回一个承诺,无论它是否完成,如果函数在执行时没有显式返回值,则该承诺将用解析,如果它返回一些值,则该承诺将解析给它,最后如果函数中的某些东西抛出,则该承诺将被拒绝。

正如你所看到的,问题在于这些承诺并没有被任何东西所期待,而且它们也没有解决任何价值问题。在回调中放置的await实际上对该值没有任何作用,就像在上面我在做并且对该值没有任何作用一样。

null

function forEach(array, callback) {
  for(const value of array) {
    callback(value);
  }
}

const values = [ 'a', 'b', 'c' ];
forEach(values, (item) => {
  console.log(item)
});