JavaScript Generator异步过度的实现详解
什么是Generator?
Generator是一种特殊的迭代(iteration)构造函数,它使用关键字 yield
来暂停函数执行,让程序流程的控制权让出去,而后再次从函数的断点开始执行。Generator内部可包含多个 yield
语句,每次执行完一个 yield
就将函数暂停,等待下一个指令。
Generator的基础语法
Generator主要使用函数生成器函数的方式,语法如下:
function* generatorFunc() {
yield 'value1';
yield 'value2';
return 'generatorFunc end';
}
当我们使用 generatorFunc()
调用时,只会返回一个迭代器(Iterator)对象,而不是直接执行函数中的语句。
const generator = generatorFunc();
console.log(generator.next()); // {value: 'value1', done: false}
console.log(generator.next()); // {value: 'value2', done: false}
console.log(generator.next()); // {value: 'generatorFunc end', done: true}
console.log(generator.next()); // {value: undefined, done: true}
当程序执行到 yield
时,会暂停代码执行,将 yield
后的值作为迭代器对象的 value
属性,并将 done
设置为 false
,等待下一次调用。当函数执行到最后一次 yield
或 return
时,将 done
设置为 true
,并返回最后一个值。
Generator的异步应用
Generator的主要应用是作为异步操作的容器。比如,我们要调用多个异步操作,需要使用回调函数嵌套,造成代码可读性降低,而使用Generator可以解决这个问题。
示例一:异步操作的演示
我们模拟一下请求两个API的情况,先看传统的回调函数写法:
function requestApi1(cb) {
setTimeout(() => {
cb('response1');
}, 1000);
}
function requestApi2(cb) {
setTimeout(() => {
cb('response2');
}, 1000);
}
requestApi1(response1 => {
console.log(response1);
requestApi2(response2 => {
console.log(response2);
});
});
这种回调嵌套的方式非常难以维护,改用Generator的方式:
function* requestApi() {
const response1 = yield requestApi1;
console.log(response1);
const response2 = yield requestApi2;
console.log(response2);
}
function asyncRequestApi(generator) {
const iterator = generator();
const next = response => {
const {value, done} = iterator.next(response);
if (!done) {
value(next);
}
};
next();
}
asyncRequestApi(requestApi);
这种方式,代码可读性明显提高,异步操作之间的关系也更清晰了。
示例二:使用Generator+Promise处理异步请求
我们借助Promise对象来把异步请求改用Promise封装,再结合Generator使用。这种方式将异步操作看作一个单独的Promise,将Generator所负责的线程与异步操作解耦。
function requestApi1() {
return new Promise(resolve => {
setTimeout(() => {
resolve('response1');
}, 1000);
});
}
function requestApi2() {
return new Promise(resolve => {
setTimeout(() => {
resolve('response2');
}, 1000);
});
}
function* requestApi() {
const response1 = yield requestApi1();
console.log(response1);
const response2 = yield requestApi2();
console.log(response2);
}
function asyncRequestApi(generator) {
const iterator = generator();
const next = response => {
const {value, done} = iterator.next(response);
if (!done) {
value.then(next);
}
};
next();
}
asyncRequestApi(requestApi);
总结
Generator提供了一种可控的、分步的方式来处理异步请求,能够解决回调函数嵌套的问题,同时能够改善代码可读性,保证异步操作之间逻辑的清晰性。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:JavaScript Generator异步过度的实现详解 - Python技术站