这是我参与2022首次更文挑战的第4天,活动详情查看:2022首次更文挑战
hi 我是小十七_,新年快乐,今天是大年初四,之前整理了从回调函数到 async 的知识,帮助大家更好的理解回调函数,分享给大家。
回调函数方式的缺点
- 不符合大脑正常的思维逻辑(从上到下)
- 使用第三方插件,会带来控制反转问题
Promise
解决了控制反转的问题
generator
解决符合大脑思维逻辑的问题
打破函数的完整运行
正常情况下,函数都会完整的自上而下运行,es6新增了一种特殊类型的函数 generator,它中间可以让步 yield,让其他的代码先执行,然后这个函数再继续运行。
// 定义一个生成器函数
function *foo(){
console.log('111');
yield; // 可以做出让步
console.log('222');
}
// 定义一个迭代器,去执行这个函数(并没有立即执行他)
var it = foo();
it.next();
console.log('333');
it.next();
// 111 333 222
1.执行 generator 的迭代器 .next() 本身会返回一个对象,对象有个 value 的属性,表示这次执行 yield 给他的之或者函数的返回值。
2.generator 和普通函数一样,都可以接收参数。
3.yield(让步)本身可以向外传递信息,也可以接收到传递的信息
function *foo(x){
var y = x * (yield 'hello'); // yield 向外传递了一个信息
return y;
}
var it = foo(6);
var res = it.next();
console.log(res, res.value); // hello,收到 yield 向外传的值
var res1 = it.next(7); // 走到 yield 暂停了,向 yield 传值
console.log(res1, res1.value); // 42
一个迭代器本身对应一个 generator 的实例,所以两个迭代器之间的执行互不影响,除非生成器里有一些全局的变量
function *foo() {
var x = yield 2;
z++;
var y = yield (x * z);
console.log( x, y, z );
}
var z = 1;
var it1 = foo();
var it2 = foo();
var val1 = it1.next().value; // 2 <-- yield 2
var val2 = it2.next().value; // 2 <-- yield 2
val1 = it1.next( val2 * 10 ).value; // 40 <-- x:20, z:2
val2 = it2.next( val1 * 5 ).value; // 600 <-- x:200, z:3
it1.next( val2 / 2 ); // 20 300 3
it2.next( val1 / 4 ); // 200 10 3
es6 中 for...of
可以遍历带有迭代器的数据结构,比如说数组,遍历过程中自动调用迭代器的 .next
方法(不传参数)
制造一个数字生成器,保存上一次迭代的结果
var makeup = (function(){
var countup;
return function(){
if(!countup){
countup = 1;
}else{
countup = countup+3;
}
return countup
}
})()
console.log(makeup()); // 1
console.log(makeup()); // 4
console.log(makeup()); // 7
generator 是解决这个事的方式
function *makeup(){
var countup;
while(true){
if(!countup){
countup = 1;
}else{
countup = countup + 3;
}
yield countup;
}
}
var it = makeup();
var res = it.next();
console.log(res.value);
var res = it.next();
console.log(res.value);
var res = it.next();
console.log(res.value);
generator 和 promise 的结合
那么,我们就需要考虑更好的写法,在解决控制反转问题的同时,代码类似于同步的写法
function foo(x, y){
return new Promise(function(resolve, reject){
resolve(2)
})
}
// 主要的 generator 函数
function *main(){
try{
var res = yield foo(1, 3); // yield 执行 foo 函数
}catch(err){
}
}
var it = main();
var res = it.next().value; // 执行 generator 函数,得到 yield 返回结果,也就是 Promise 实例
res.then(function(res){
it.next(res); // 向 yield 传值
}, function(err){
it.throw(res)
})
async 和 await
async 实质上就是 generator + promise
如果 await 后面跟的是 Promise,async 会自动暂停等待 Promise 决议之后,再执行接下来的语句
function foo(x, y){
return new Promise(function(resolve, reject){
resolve(2)
})
}
async function main(){
try{
var res = await foo(1, 3);
console.log(res); // 2
console.log(333); // 333(在后)
}catch(err){
}
}
main();
在定时器执行完成后,在执行后面的内容
function timeout(){
return new Promise(function(resolve, reject){
setTimeout(resolve, 10000);
})
}
async function wait(){
var res = await timeout();
console.log('后面的内容'); // 10秒后打印出来
}
wait();