首页 > 解决方案 > 函数不会等到它们被解决

问题描述

我正在尝试按顺序一次执行一个功能。使用承诺,我相信它应该有效,但对我来说,它不起作用。我进行了一些研究并发现了这个问题,其中一个答案解释了使用 Promises,这就是我一直在尝试做的事情。

这是功能:

async function loadCommands () {
  return new Promise((resolve, reject) => {
    let commands = 0;
    readdir('./commands/', (error, files) => {
      if (error) reject(error);
      for (const file of files) {
        if (!file.endsWith('.js')) return;
        commands++;
      }
    }
    resolve(commands); // this is in my code, I forgot to put it - sorry commenters
  });
};

async function loadEvents () {
  return new Promise(async (resolve, reject) => {
    let events = 0;
    readdir('./events/', (error, files) => {
      if (error) reject (error);
      for (const file of files) {
        if (!file.endsWith('.js')) return;
        events++
      }
    });
    resolve(events);
  });
};

然后我在异步函数中使用 await 来尝试确保每个函数在进入下一个函数之前解析:

console.log('started');
const events = await loadEvents();
console.log(events);
console.log('load commands');
const commands = await loadCommands();
console.log(commands);
console.log('end')

在控制台中,这是链接的(请记住,我没有文件,./events/我有一个文件./commands/):

start
0 // expected
load commands
0 // not expected, it's supposed to be 1
end

我究竟做错了什么?我希望这些功能按顺序运行。我已经尝试过使用它而不是函数,它只是一个异步函数中的裸代码,但仍然遇到了问题。

标签: javascriptpromiseasync-await

解决方案


您永远不会resolve()在 中创建的承诺loadCommands,以及在回调发生之前resolve()创建的承诺。loadEventsreaddir

此外,不要在非承诺回调中执行任何逻辑。仅将new Promise构造函数用于promisify,并在异步回调中仅调用resolve/ :reject

function readdirPromise(path) {
    return new Promise((resolve, reject) => {
        readdir(path, (err, files) => {
            if (err) reject(err);
            else resolve(files);
        });
    });
});

或者干脆

import { promisify } from 'util';
const readdirPromise = promisify(readdir);

然后你可以在你的实际逻辑函数中使用这个承诺:

async function countJsFiles(path) {
    const files = await readdirPromise(path);
    let count = 0;
    for (const file of files) {
        if (file.endsWith('.js'))
            count++;
        // I don't think you really wanted to `return` otherwise
    }
    return count;
}
function loadCommands() {
    return countJsFiles('./commands/');
}
function loadEvents() {
    return countJsFiles('./events/');
}

推荐阅读