企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
async/await is built on top of promises. `async`关键字放在`function`关键字前定义了一个异步处理函数,该函数默认返回的是一个Promise对象。 `await`关键字,只能在`async`定义的函数内出现,表示开始一个异步过程并等待该过程的结果。 [TOC] ## async/await [[MDN-async/await](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Async_await)] We've included the `async` keyword before the function keyword. This is necessary — you have to create an async function to define a block of code in which you'll run your async code; `await` only works inside of async functions. example: ~~~js async function fetchAndDecode(url, type) { let response = await fetch(url); let content; if(type === 'blob') { content = await response.blob(); } else if(type === 'text') { content = await response.text(); } return content; } async function displayContent() { let coffee = fetchAndDecode('coffee.jpg', 'blob'); let tea = fetchAndDecode('tea.jpg', 'blob'); let description = fetchAndDecode('description.txt', 'text'); let values = await Promise.all([coffee, tea, description]); let objectURL1 = URL.createObjectURL(values[0]); let objectURL2 = URL.createObjectURL(values[1]); let descText = values[2]; let image1 = document.createElement('img'); let image2 = document.createElement('img'); image1.src = objectURL1; image2.src = objectURL2; document.body.appendChild(image1); document.body.appendChild(image2); let para = document.createElement('p'); para.textContent = descText; document.body.appendChild(para); } displayContent() .catch((e) => console.log(e) ); ~~~ By using `await` here we are able to get all the results of the three promises returned into the `values` array, when they are all available, in a way that looks very much like sync code. We've had to wrap all the code in a new async function, `displayContent()`, and we've not reduced the code by a lot of lines, but being able to move the bulk of the code out of the `.then()` block provides a nice, useful simplification. For error handling, we've included a `.catch()` block on our `displayContent()` call; this will handle errors ocurring in both functions. >[warning] wrap your awaited promises inside an async function. The `await` keyword blocks execution of all the code after it until the promise fulfills, exactly as it would with a synchronous operation. This is means that your code could be slowed down by a significant number of awaited promises happening straight after one another. Each await will wait for the previous one to finish, whereas actually what you want is for the promises to begin processing simultaneously, like they would do if we weren't using async/await. There is a pattern that can mitigate this problem — setting off all the promise processes by storing the `Promise` objects in variables, and then awaiting them all afterwards. Example: **timeoutPromise()**: a custom promise function that fakes an async process with a [`setTimeout()`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout) call: ~~~js function timeoutPromise(interval) { return new Promise((resolve, reject) => { setTimeout(function(){ resolve("done"); }, interval); }); }; ~~~ **slow-async-await.html**, `timeTest()` ~~~js // async function timeTest() { await timeoutPromise(3000); await timeoutPromise(3000); await timeoutPromise(3000); } ~~~ Each subsequent one is forced to wait until the last one finished — if you run the first example, you'll see the alert box reporting a total run time of around 9 seconds. **fast-async-await.html**, `timeTest()` ~~~js async function timeTest() { const timeoutPromise1 = timeoutPromise(3000); const timeoutPromise2 = timeoutPromise(3000); const timeoutPromise3 = timeoutPromise(3000); await timeoutPromise1; await timeoutPromise2; await timeoutPromise3; } ~~~ Here we store the three `Promise` objects in variables, which has the effect of setting off their associated processes all running simultaneously. Next, we await their results — because the promises all started processing at the same time, the promises will all fulfill at the same time; when you run the second example, you'll see the alert box reporting a total run time of just over 3 seconds! ### Async/await class methods you can even add `async` in front of class/object methods to make them return promises, and `await` promises inside them. ~~~js class Person { constructor(first, last, age, gender, interests) { this.name = { first, last }; this.age = age; this.gender = gender; this.interests = interests; } async greeting() { return await Promise.resolve(`Hi! I'm ${this.name.first}`); }; farewell() { console.log(`${this.name.first} has left the building. Bye for now!`); }; } let han = new Person('Han', 'Solo', 25, 'male', ['Smuggling']); ~~~ The first class method could now be used something like this: ~~~js han.greeting().then(console.log); ~~~