将 Async/Await 与生成器函数结合使用
介绍
ES2015 为开发者社区带来了许多 JavaScript 语言的新功能。这些功能包括生成器函数和 async/await。生成器函数可让您暂停和继续执行程序。相比之下,async/await 可让您编写异步代码,而不会陷入“回调地狱”,而编写标准承诺时则有可能陷入这种困境。乍一看,这些功能似乎毫无关联。但是,在本指南中,我将向您展示如何在生成器函数上使用 async/await。
生成器功能概述
生成器函数的定义是一种可以暂停并在稍后恢复的函数,同时能够在每个暂停点向函数传递值或从函数传递值。
生成器函数可以运行至完成,但并非必须如此。到目前为止,在 Javascript 中,函数始终运行至完成。现在我们可以编写永不停止“运行”的生成器函数。我将其放在引号中,因为生成器函数不会陷入无限循环。只是我们可能不需要执行函数的其余部分。
生成器函数的语法与普通函数并没有太大区别。我们需要在函数关键字和函数名称之间添加一个星号。星号放在哪里并不重要。它只需要在名称之前。
function* fetchData() {...}
// or
function * fetchData() {...}
// or
function *fetchData() {...}
有一个重要的部分真正展示了生成器的强大功能。您希望能够暂停此功能。要暂停执行,您需要使用yield关键字。
function* fetchData() {
const data = yield fetchMovies();
}
当你执行该函数时,它会返回一个可以使用next()方法控制的迭代器:
function* fetchMovies() {
const data = yield fetch();
}
const iter = fetchData();
iter.next(); // run the generator function up to the `yield` keyword.
使用yield关键字告诉函数停止并等待。暂停期间,其他任何操作都不会执行,直到发生下一个调用。
next()方法返回一个具有两个属性(value 和 done)的对象。value是传递给yield函数的值, done是一个布尔值,用于告知生成器是否已完成执行。此对象也称为IteratorResult接口(来自规范)。
这是一个更完整的例子:
function* fetchUsers() {
yield fetch('https://jsonplaceholder.typicode.com/users')
.then(resp => resp.json())
.then(users => {
return users;
});
}
const usersIt = fetchUsers();
usersIt.next().value.then(resp => console.log(resp));
复习一下 Async/Await
异步函数:
- 始终返回承诺
- 函数声明前需要async关键字
- 使用 try/catch 块来处理“被拒绝”的承诺
- Lets you skip putting .then(...) on async calls
Async functions can help improve the readability of asynchronous code. For a function to use async/await, it only needs to be declared as async. Here's an example of the fetchUsers function rewritten into a strictly async function (no generator):
async function fetchUsers() {
const response = await fetch('https://jsonplaceholder.typicode.com/users');
const users = await response.json();
return users;
}
You can still make this function a generator and pause the function whenever you'd like:
async function* fetchUsers() {
const response = await fetch('https://jsonplaceholder.typicode.com/users');
yield await response.json();
}
const it = fetchUsers();
it.next().then(({ value, done }) => {
console.log(value);
});
What you may notice here is that the next() method isn't returning the IteratorResult interface { value, done }. It is instead returning a promise. This is because async functions return promises. Calling next() advances function execution and returns any value passed to the next yield. Since this is an async function, that value will be a promise that needs to be resolved. In this case, the promise will resolve with the value of response.json(). That resolved value is still assigned to the iterator's { value, done } object, which I am destructuring in the code above.
Conclusion
Remember, when executing an async generator:
- Advancing an async generator function with next() will return a promise
- That promise will resolve with the IteratorResult interface of { value, done }
I hope this helps explain how to use async/await with a generator function. For more on generators, please check out my course Javascript Generators and Iterators, where I give a complete introduction with examples of generator functions and iterators.
免责声明:本内容来源于第三方作者授权、网友推荐或互联网整理,旨在为广大用户提供学习与参考之用。所有文本和图片版权归原创网站或作者本人所有,其观点并不代表本站立场。如有任何版权侵犯或转载不当之情况,请与我们取得联系,我们将尽快进行相关处理与修改。感谢您的理解与支持!
请先 登录后发表评论 ~