如何在异步继续之前等待查询者回答被处理(fs.writeFile)

How to wait inquirer answer to be processed (by fs.writeFile) before continuing asynchronously

所以我有这个异步函数 inquirer 和 fs.writeFile inside

(async () => {

...

  if (process.env.IG_USERNAME && process.env.IG_PASSWORD) {
    console.log(`Used as ${chalk.green(process.env.IG_USERNAME)}`);
  } else {
    console.log(`\nInstagram account data is not yet put in \nInputting in...`);

    await inquirer.prompt(questions).then((answers) => {
      let file = `IG_USERNAME=${answers.username}\nIG_PASSWORD=${answers.password}\n#ONLINE_MODE=true`;
      fs.writeFile(".env", file, (err) => {
        if (err) console.log("Something went wrong..");
        else console.log(`Used as ${chalk.green(process.env.IG_USERNAME)}`);
      });
    });
  }

  await login();

...

})();

login(); 函数需要 .env 变量,我使用查询器输入它,但是 login(); 函数在查询器答案得到处理之前执行。

我应该怎么做才能让 login(); 等到 fs.writeFile 完成?

简短的回答是只在你的 .then() 中使用 promise-based 异步操作,这样你就可以正确地链接所有的承诺,然后更高级别的 await 将等待一切​​。在这种情况下,您可以使用 return fs.promises.writeFile(...)(而不是 fs.writeFile(...)),因为 fs.promises.writefile(...) returns 一个承诺,然后将正确地与父承诺链接。

(async () => {

...

  if (process.env.IG_USERNAME && process.env.IG_PASSWORD) {
    console.log(`Used as ${chalk.green(process.env.IG_USERNAME)}`);
  } else {
    console.log(`\nInstagram account data is not yet put in \nInputting in...`);

    await inquirer.prompt(questions).then((answers) => {
      let file = `IG_USERNAME=${answers.username}\nIG_PASSWORD=${answers.password}\n#ONLINE_MODE=true`;
      return fs.promises.writeFile(".env", file);  
    });
  }

  await login();

...

})();

或者,再简化一点:

(async () => {

...

  if (process.env.IG_USERNAME && process.env.IG_PASSWORD) {
    console.log(`Used as ${chalk.green(process.env.IG_USERNAME)}`);
  } else {
    console.log(`\nInstagram account data is not yet put in \nInputting in...`);

    const answers = await inquirer.prompt(questions);
    const file = `IG_USERNAME=${answers.username}\nIG_PASSWORD=${answers.password}\n#ONLINE_MODE=true`;
    await fs.promises.writeFile(".env", file);  
  }

  await login();

...

})();

通常使用带有 promise 的 .then()await,而不是同时使用。 login() 之前被执行了,因为承诺是通过 .then().

解决的

并且在调用 login() 之前没有返回给 await 的承诺。

解决方案 1: 快速修复是在 fs.writeFile 的回调中解决 await login();,但是 login() 的错误将不得不也被处理,这只会使代码开始时更加冗长。

const answers = await inquirer.prompt(questions);
let file = `IG_USERNAME=${answers.username}\nIG_PASSWORD=${answers.password}\n#ONLINE_MODE=true`;
fs.writeFile(".env", file, async (err) => {
  if (err) console.error("Error:fs.writeFile()::", err);
  else console.log(`Used as ${chalk.green(process.env.IG_USERNAME)}`);
  try {
    await login();
  } catch (e) {
    console.error("Error::login():", e);
  }
});

解决方案 2: util.promisify 节点 >= V8

做出 fs.writeFile 承诺。

const fs = require("fs");
const { promisify } = require("util");
const promisedWriteFile = promisify(fs.writeFile);

try {
  const answers = await inquirer.prompt(questions);
  let file = `IG_USERNAME=${answers.username}\nIG_PASSWORD=${answers.password}\n#ONLINE_MODE=true`;
  await promisedWriteFile(".env", file);
  await login();
} catch (error) {
  console.error("Any error::", error);
}

解决方案 3: fs Promises API with Node >= V10

try {
  const answers = await inquirer.prompt(questions);
  let file = `IG_USERNAME=${answers.username}\nIG_PASSWORD=${answers.password}\n#ONLINE_MODE=true`;
  await fs.promises.writeFile(".env", file);
  await login();
} catch (error) {
  console.error("Any error::", error);
}