【问题标题】:How to wait inquirer answer to be processed (by fs.writeFile) before continuing asynchronously如何在异步继续之前等待查询者的回答被处理(通过 fs.writeFile)
【发布时间】:2020-12-05 13:18:09
【问题描述】:

所以我有这个异步函数,里面有查询器和 fs.writeFile

(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 完成?

【问题讨论】:

    标签: javascript node.js fs inquirer


    【解决方案1】:

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

    (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();
    
    ...
    
    })();
    

    【讨论】:

    • 我尝试了这两个示例,但下一个语句/函数似乎首先执行,即使我这样做console.log(process.env.IG_USERNAME) 它仍然给我undefined
    • 我想我找到了问题所在。这不是关于承诺,而是关于我在程序顶部需要的 .env 文件,因此在下次运行程序时再次需要它之前它不会改变。
    【解决方案2】:

    通常将.then()await 与promise 一起使用,而不是同时使用。并且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 使用 Node >= 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 使用 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);
    }
    

    【讨论】:

    • 我试过了,但来自.env 的数据即使在writeFile() 之后仍然未定义
    • @SyakhiskAl-azmi 这应该可以!检查.env 文件是否具有let file 字符串的值?这可能是您从.env 文件中读取值的方式。请在问题中更新它以获得更多上下文。
    • 是的,它应该有效。数据被输入到 .env 但我认为我的问题是我加载了 .env 是恒定的,我仍然找不到重新加载它的方法。谢谢!
    • 我假设您正在使用dontenv 作为环境变量,并且您怀疑它不会重新加载.env 文件并分配变量(如果在某些代码中间更改了.env) .一种方法:overriding the env variables listed here。另外请考虑接受其中一个答案,因为它们解决了您问题中提到的承诺问题。祝你好运! ?
    猜你喜欢
    • 2017-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多