生成器 Generator
一、基础
generator函数 可以通过yield关键字,将函数挂起,为了改变执行流提供了可能,同时为了做异步编程提供了方案
与普通函数的区别
1.function后面 函数名之前有个*
2.只能在函数内部使用yield表达式,让函数挂起
总结:generator函数是分段执行的,yield语句是暂停执行 而next()恢复执行
function* func() {
console.log('one');
yield 2;
console.log('two');
yield 3;
console.log('end');
}
// 返回一个遍历器对象 可以调用next()
let fn = func(); //调用的时候不会进入到函数内部,只有调用next的时候才会进入函数内部并执行 yield
console.log(fn.next()); //done: false value: 2
console.log(fn.next()); //done: false value: 3
console.log(fn.next()); //done: true value: undefined
生成器计算
function* add() {
console.log('start');
// x 可真的不是yield '2'的返回值,它是next()调用 恢复当前yield()执行传入的实参
let x = yield '2';
console.log('one:'+x); //one:20
let y = yield '3';
console.log('two:'+y); //two:30
return x+y;
}
const fn = add();
console.log(fn.next()); //{value:'2',done:false}
console.log(fn.next(20)); //{value:'3',done:false}
console.log(fn.next(30)); //{value:50,done:true}
使用场景1:为不具备Interator接口的对象提供了遍历操作
function* objectEntries(obj) {
// 获取对象的所有的key保存到数组 [name,age]
const propKeys = Object.keys(obj);
for (const propkey of propKeys) {
yield [propkey, obj[propkey]]
}
}
const obj = {
name: '小马哥',
age: 18
}
obj[Symbol.iterator] = objectEntries;
console.log(obj); //{name: "小马哥", age: 18, Symbol(Symbol.iterator): ƒ}
for (let [key, value] of objectEntries(obj)) {
console.log(`${key}:${value}`); //name:小马哥 //age:18
}
二、应用
1、ajax请求
function* main() {
let res = yield request(
'https://free-api.heweather.net/s6/weather/now?location=beijing&key=4693ff5ea653469f8bb0c29638035976'
)
console.log(res);
// 执行后面的操作
console.log('数据请求完成,可以继续操作');
}
const ite = main();
ite.next();
function request(url) {
$.ajax({
url,
method: 'get',
success(res) {
ite.next(res);
}
})
}
2、
(1)加载loading…页面
(2)数据加载完成…(异步操作)
(3)loading关闭掉
function* load() {
loadUI();
yield showData();
hideUI();
}
let itLoad = load();
itLoad.next();
function loadUI() {
console.log('加载loading...页面');
}
function showData() {
// 模拟异步操作
setTimeout(() => {
console.log('数据加载完成');
itLoad.next();
}, 1000);
}
function hideUI() {
console.log('隐藏loading...页面');
}