异步函数完成所有异步调用后,事件循环是否会再次更改?

时间:2018-09-21 15:09:05

标签: javascript asynchronous async-await

让我们考虑以下代码:

async function testFunction() {
  // event loop 1 - before any "await", we are still in original event loop, right?
  const result = await Promise.resolve('abc');
  // event loop 2 - we have a new event loop
  return result;
}

// event loop 1
testFunction().then(result => {
  // event loop 2? Or new event loop?
})

async函数完成所有异步操作之后,事件循环会再次更改吗?return语句之前的事件循环是否与then语句中的相同? ?

有没有简单的方法可以检查它?

我正在使用一些需要在同一事件循环中执行的同步API,我想确保它可以正常工作。

编辑:

更清楚地说,这是现实生活中的例子:

async function dbTransaction(tableName, transactionMode) {
  const db = await _dbPromise;
  return db.transaction([tableName], transactionMode).objectStore(tableName);
}

我可以使用此异步函数返回的事务吗?
一些相关的MDN信息:
https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API/Using_IndexedDB#Adding_data_to_the_database

重要的报价:

  

现在您需要进行交易,以了解其生命周期。   事务与事件循环紧密相关。如果你做一个   交易并返回事件循环而不使用它,然后   交易将变为无效。

编辑2:
还有一件事-答案是肯定的-该交易在const objectStore = await dbTransaction(DB_IMAGE, DB_OP_READWRITE)之后可用。仅当我等待其他内容时,我才会收到TRANSACTION_INACTIVE_ERR错误-这是有道理的。 那是设计使然吗?这是否意味着它确实在同一事件循环迭代中?

1 个答案:

答案 0 :(得分:1)

事务仅在给定堆栈上有效。 完成一些异步工作后,即浏览器会在此处为indexedDB提供处理程序:

const db = await _dbPromise;

创建了一个新的堆栈,该堆栈一直持续到该函数结束。 但是除了主堆栈之外,还有一个微任务堆栈,并且在该堆栈上包含来自promise和观察者的所有回调。如果在执行给定堆栈中的指令时将promise标记为已解决,则在主堆栈清空后仍可立即进行调用。 (您可以将堆栈+微任务视为循环的一个“滴答声”,之后javascript将控制权传递回事件循环,以决定下一步该做什么)。

在您的示例中:

async function testFunction() {
  // tick 1 synchronous
  const result = await Promise.resolve('abc');
  // tick 1 microtask 1 (up resolved through the execution of the stack)
  return result;
}

// tick 1
testFunction().then(result => {
  // tick 1 microtask 2 (resolved through the execution of microtask 1)
})

您可以通过查看效果面板来获取一些信息: enter image description here

该视频可能会清除事件循环是什么以及它如何工作:https://vimeo.com/254947206