try 块中的 return 语句是否等待 finally 块中的 await 语句?

drm*_*wer 5 javascript async-await

考虑以下片段:

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();
}
Run Code Online (Sandbox Code Playgroud)

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

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

ter*_*rse 3

下面是一些简单的测试代码,显示该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();
Run Code Online (Sandbox Code Playgroud)

但正如OP所指出的,在finally块完成之前,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));
Run Code Online (Sandbox Code Playgroud)

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

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));
Run Code Online (Sandbox Code Playgroud)