将promise函数重构为es6格式,await实际上并不等待

Refactoring promise function to es6 format, await doesn't actually await

所以我只是重新访问一些旧代码来整理和现代化我的 Partum-React 项目中的一些语法。但是当我将这个特定的旧传统 function() return new Promise... 重新格式化为 async () => ...return... 类型的函数时,它似乎并没有等待函数完成。我找到的答案似乎并没有解决我的问题,因为据我所知,我的异步函数编写正确并且应该按预期工作。我也已经将一些较旧的 function/promise 函数重新格式化为异步函数,没有任何问题。所以我很困惑为什么这个特定的功能似乎没有被正确地包装在一个承诺中。

按预期工作的旧函数,程序在继续执行之前正确等待函数完成(在 /src 文件夹中的 helper.js 中找到):

function shell(command, log = false, cb = null) {
  return new Promise((resolve, reject) => {
    exec(command, (err, stdout, stderr) => {
      if (err) {
        reject(err);
      } else {
        if (cb) cb(stdout);
        if (log) process.stdout.write(`\n${stdout}\n\n`);
        resolve({
          stdout,
          stderr,
        });
      }
    });
  });
}

重写的函数,在调用 await 时似乎没有正确等待。连续 shell 调用是 运行 同步导致 git 出错。我敢肯定这是我的一个小错误,但我似乎看不到它。据我所知,这个函数应该被正确地包装在一个承诺和函数中:

const shell = async (command, log = false, cb = null) => {
  exec(command, (err, stdout, stderr) => {
    if (err) throw err;
    if (cb) cb(stdout);
    if (log) process.stdout.write(`\n${stdout}\n\n`);
    return {
      stdout,
      stderr,
    };
  });
};

这是调用函数的地方(在 /src 文件夹的 initializer.js 中找到)(我知道,这也需要一些主要清理):

finalize() {
    return new Promise((resolve, reject) => {
      process.stdout.write('finalizing project\n');
      copy(this.tempPath, this.destination, (err) => {
        if (err) {
          reject(err);
        } else {
          process.stdout.write('cleaning up temporary files\n');
          rmdir(this.tempPath, async (err) => { // eslint-disable-line
            if (err) {
              reject(err);
            } else {
              try {
                await shell(`mkdir ${path.join(this.destination, this.options.componentPath)}`);

                if (this.options.redux) {
                  await shell(`mkdir ${path.join(this.destination, this.options.reduxPath, this.options.actionPath)}`);
                }

                await shell(`git -C ${this.destination} init`);
                await shell(`git -C ${this.destination} add .`);
                await shell(`git -C ${this.destination} commit -m 'Initialized with Partum-React'`);

                process.stdout.write(
                  `\nrunning npm install inside ${this.destination}\n`,
                );
                await npmInstall(this.destination, this.silent);

                resolve(true);

              } catch (err) { // eslint-disable-line
                reject(err);
              }
            }
          });
        }
      });
    });
  }
};

控制台日志记录 shell(....) 没有等待日志 Promise {undefined}

控制台日志记录 await shell(....) 和等待日志 {undefined}

在此先感谢您的帮助!

const shell = async (command, log = false, cb = null) => {
  /*problem lies here, because most probably this is a async function and 
  therefore undefined is returned from this function as resolved value*/

  exec(command, (err, stdout, stderr) => {
    if (err) throw err;
    if (cb) cb(stdout);
    if (log) process.stdout.write(`\n${stdout}\n\n`);
    return {
      stdout,
      stderr,
    };
  });
};

不对,你的async函数写得不对。你 . If something provides only a callback API, you need to promisify 它才能使用 await 它。

你应该做的

function shell(command) {
  return new Promise((resolve, reject) => {
    exec(command, (err, stdout, stderr) => {
      if (err) {
        reject(err);
      } else {
        resolve({stdout, stderr});
      }
    });
  });
}
function copy(source, destination) {
  return new Promise((resolve, reject) => {
    …
  });
}
function rmdir(path) {
  return new Promise((resolve, reject) => {
    …
  });
}

然后您可以使用 async/await:

编写 finalise 函数
async finalize() {
  process.stdout.write('finalizing project\n');
  await copy(this.tempPath, this.destination);
  process.stdout.write('cleaning up temporary files\n');
  await rmdir(this.tempPath);
  await shell(`mkdir ${path.join(this.destination, this.options.componentPath)}`);
  if (this.options.redux) {
    await shell(`mkdir ${path.join(this.destination, this.options.reduxPath, this.options.actionPath)}`);
  }
  await shell(`git -C ${this.destination} init`);
  await shell(`git -C ${this.destination} add .`);
  await shell(`git -C ${this.destination} commit -m 'Initialized with Partum-React'`);
  process.stdout.write(`\nrunning npm install inside ${this.destination}\n`);
  await npmInstall(this.destination, this.silent);
  return true;
}