简体   繁体   中英

Does event loop changes again after async function finishes all asynchronous calls?

Let's consider this code:

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?
})

Does event loop changes again after async function done all asynchronous operations? Is the event loop right before return statement the same as in the then statement?

And is there an easy way to check it?

I'm working with some synchronous API that needs to be executed in the same event loop and I want to be sure it will work.

EDIT:

To make it more clear, this is the real life example:

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

Can I use the transaction returned by this asynchronous function?
Some related MDN info:
https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API/Using_IndexedDB#Adding_data_to_the_database

And important quote:

Now that you have a transaction you need to understand its lifetime. Transactions are tied very closely to the event loop. If you make a transaction and return to the event loop without using it then the transaction will become inactive.

EDIT 2:
One more thing - the answer is yes - the transaction is usable after const objectStore = await dbTransaction(DB_IMAGE, DB_OP_READWRITE) . Only if I await something else I get TRANSACTION_INACTIVE_ERR error - which makes sense.
So is it by design? Does it mean it is indeed in the same event loop iteration?

A transaction is only valid on a given stack. When some asynchronous work is done, ie the browser gets a handler to indexedDB here:

const db = await _dbPromise;

a new stack is created and it continues till the end of that function. But apart from the main stack, there's also a microtask stack and on that stack go all callbacks from promises and observers. If a promise is marked as resolved while executing instructions from a given stack, it is immediately called after the main stack empties and a transaction is still available there. (You can think of stack + microtasks as one 'tick' of a loop after which javascript passes control back to the event loop that decides what to do next).

So in your example:

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)
})

You can get some info by checking performance panel: 在此处输入图片说明

This video might clear what an event loop is and how it works: https://vimeo.com/254947206

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM