【问题标题】:Why isn't Await blocking the next line of code?为什么 Await 不阻塞下一行代码?
【发布时间】:2019-08-21 22:20:28
【问题描述】:

我正在使用异步函数来启动服务器,检查 url 是否返回 200,然后运行我的测试,但我的 checkUrl 函数在运行下一行代码之前没有完成。

我正在使用 axios 包来 ping 状态代码的 url,并且我一直在尝试 async/await 和 Promise.resolve() 的几种变体。

function checkUrl(url) {
  console.log(`Checking for ${url}`);

  return axios
    .get(url)
    .then(function(res) {
      const message = `${url} is status code: ${res.status}`;

      return res;
    })
    .catch(function(err) {
      console.log("Will check again in 5 seconds");
      setTimeout(() => {
        return checkUrl(url);
      }, 5000);
    });
}

async function init() {
  let val;

  console.log("Running tests:::");
  // start server in react-integration directory
  shell.exec("BROWSER=none yarn start", {
    cwd: "sampleIntegration/react-integration",
    async: true
  });
  // check server has started
  val = await checkUrl("http://localhost:3000");

  console.log(`value from checkUrl promise: ${val}`);
}

我希望 val 变量是在我的 checkUrl 函数中从 Promise.resolve() 返回的消息。

val 未定义返回。

【问题讨论】:

  • 值在两种情况下都返回undefined 还是仅针对错误情况?
  • shell.exec 是异步的,所以当你调用checkurl 时,服务器可能还不可用,从而导致axios.get 进入catch 分支。从那里,您不会返回任何内容,因此最终结果是未定义的
  • console.log 仅在 catch 块日志之后运行一次。 Checking for http://localhost:3000 Will check again in 5 seconds value from checkUrl promise: undefined 一旦承诺解决,我得到http://localhost:3000 is status code: 200 但函数下面的行已经运行。
  • 我也不确定,当 http 状态码为 != 2xx 时 axios 是解析还是拒绝
  • return 内的 setTimeout 不做,你可能认为它做。该块与 catch 块的结果完全无关。事实上,你的 catch 块还没有任何结果,val == undefined.

标签: javascript promise async-await axios


【解决方案1】:

问题是,catch 块中的setTimeout。这是异步的,但 catch 块会立即返回。因为它没有任何东西要返回,所以它返回 undefined。要解决此问题(并保持您期望的等待行为),您可以执行以下操作:

function checkUrl(url) {
  console.log(`Checking for ${url}`);

  return axios.get(url)
    .then(res => {
      const message = `${url} is status code: ${res.status}`;
      return res;
    })
    .catch(err => {
      console.log('Will check again in 5 seconds');
      return new Promise((resolve) => {
         setTimeout(resolve, 5000);
      }).then(() => checkUrl(url));
    });
}

这将使 Promise 在 5 秒后解析,并在解析时调用 checkUrl。

【讨论】:

  • 干得好@derpirscher。我没有看到你的答案,但看起来我们在同一页面上。感谢您的帮助!
猜你喜欢
  • 2020-10-30
  • 2017-01-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-19
相关资源
最近更新 更多