【问题标题】:Does a return statement in the try block wait for an await statement in the finally block?try 块中的 return 语句是否等待 finally 块中的 await 语句?
【发布时间】:2021-01-27 02:27:38
【问题描述】:

考虑以下 sn-p:

try {
    const client = getClientThatMustBeClosed();
    const data = await shortRunningOperation(client);
    return Promise.resolve(data);
} catch (error) {
    return Promise.reject(error);
} finally {
    // any exception in the following function is caught and dealt with internally...
    await longRunningOperation(client);
    client.close();
}

理想情况下,我想在shortRunningOperation() 完成后立即将数据返回给调用函数,而不是等待longRunningOperation() 完成。但是关闭client 必须等到longRunningOperation() 完成之后。

这个jsfiddle 建议return 语句等待finally 块完成......在这种情况下,在不等待longRunningOperation() 完成的情况下尽快将数据返回到调用函数的正确方法是什么?

【问题讨论】:

  • return Promise.resolve(data) 太过分了。只需return datareturn error。但是一旦你使用return,函数执行就结束了。我认为await longRunningOperation 不会发生。
  • 似乎很容易尝试和查看。使用setTimeoutconsole.logs 设置一些async 函数,看看会发生什么。

标签: javascript async-await


【解决方案1】:

这里有一些简单的测试代码,显示finally 块确实执行,即使在try 块返回之后。

function wait (ms) {
  return new Promise(resolve => {
    setTimeout(resolve, ms);
  })
}

async function test () {
  try {
    await wait(1000);
    console.log('try block complete');
    return;
  } catch (err) {
    console.log('catch err:', err);
    return;
  } finally {
    await wait(3000);
    console.log('finally block complete');
  }
}

test();

但正如 OP 所说,在 finally 块完成之前,不会返回 try 块值。

如果立即需要 try 返回值,请不要使用 finally 块。相反,将长时间的清理代码放在 try 块中,但不要使用 await

function wait (ms) {
  return new Promise(resolve => {
    setTimeout(resolve, ms);
  })
}

async function test () {
  try {
    await wait(1000);
    console.log('try complete');
    
    // put cleanup here without using await
    wait(3000).then(() => {
      console.log('cleanup complete');
    });
    
    return 'try return';
  } catch (err) {
    console.log('catch err:', err);
    return err;
  }
}

test().then(result => console.log('result:', result));

更新:您可以使用finally 块而不阻塞(延迟)try 返回,但前提是finally 块不包含returnawait .

function wait(ms) {
  return new Promise((resolve) => {
    setTimeout(resolve, ms);
  });
}

async function test() {
  try {
    await wait(1000);
    console.log('try complete');
    return 'try return';
  } catch (err) {
    console.log('catch err:', err);
    return err;
  } finally {
    // cleanup without await
    wait(3000).then(() => {
      console.log('long duration cleanup complete');
    });
    // do not return here
  }
}

test().then((result) => console.log('result:', result));

【讨论】:

  • try 块完成,但函数实际上是否只在 finally 块完成后返回一个值(在您的情况下为 undefined)?我编辑了我的问题以包含一个更好地说明这种细微差别的 jsfiddle。就我而言,我想尽快获得返回值。
  • 这里是您的 sn-p 修改为包含返回值:jsfiddle.net/q841k9x0
  • @drmrbrewer 见第二个代码sn-p,它在尝试结果可用时立即返回,并执行长时间的清理。
  • 狡猾...“旧”.then().catch() 和“新”async/await 的组合!这是一个稍微修改过的版本(主要是为了我自己的利益),它试图使这个模型更接近我在实践中的目标:jsfiddle.net/gb7oqvc0 ...谢谢!
猜你喜欢
  • 2013-06-04
  • 2020-06-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-07
  • 2011-04-15
  • 2017-07-04
  • 1970-01-01
相关资源
最近更新 更多