博客: https://blog.csdn.net/qtfying
掘金: https://juejin.im/user/57739929c4c9710055376671
QQ: 2811132560
邮箱: qtfying@gamil.com
咱们书接上回,聊到哪了来着,奥,Generate的遍历~~~
没有看到上篇的文章,来来来,我带你传送
生动形象解密Promise、Generator 函数、Async 函数三者之间的关系(上)
Generator
for … of
next()方法会执行generator的代码,然后,每次遇到yield x;就返回一个对象{value: x, done: true/false},然后“暂停”。返回的value就是yield的返回值,done表示这个generator是否已经执行结束了。如果done为true,则value就是return的返回值。
当执行到done为true时,这个generator对象就已经全部执行完毕,不要再继续调用next()了,此时也不需要我们自己判断done。
而如果用for … of可以对Generator进行遍历,自动循环遍历 Generator 函数运行时生成的Iterator对象,并且此时不再需要调用next方法
function* foo() {
yield 1;
yield 2;
yield 3;
yield 4;
yield 5;
return 6;
}
for (let v of foo()) {
console.log(v);
}
// 1 2 3 4 5
上面代码使用for…of循环,依次显示 5 个yield表达式的值。这里需要注意,一旦next方法的返回对象的done属性为true,for…of循环就会中止,且不包含该返回对象,所以上面代码的return语句返回的6,不包括在for…of循环之中。
作用
generator和普通函数相比,有什么用?
从上面的例子中我们看的出来,就是把异步回调代码变成“同步”代码,天然的适合ajax请求,等我贴下代码来对比他们的区别:
我们最原始的写法是这样的
ajax('http://url-1', data1, function (err, result) {
if (err) {
return handle(err);
}
ajax('http://url-2', data2, function (err, result) {
if (err) {
return handle(err);
}
ajax('http://url-3', data3, function (err, result) {
if (err) {
return handle(err);
}
return success(result);
});
});
});
用到Promise来实现请求可以上一篇文章的具体示例:
生动形象解密Promise、Generator 函数、Async 函数三者之间的关系(上)
如果嫌烦,姑且就贴出一段试试,加深理解:
let promise = new Promise((resolve,reject) => {
ajax('第一个请求').success(function(res){
resolve(res);
})
})
promise.then(res => {
return new Promise((resovle,reject) => {
ajax('second').success(function(res){
resolve(res)
})
})
}).then(res => {
return new Promise((resovle,reject) => {
ajax('第二个请求').success(function(res){
resolve(res)
})
})
}).then(res => {
// 串行完毕你要做的xxx可以开始了
})
而用Generator怎么来做这样事情的呢?
function* ajax {
try {
r1 = yield ajax('http://url-1', data1);
r2 = yield ajax('http://url-2', data2);
r3 = yield ajax('http://url-3', data3);
success(r3);
}
catch (err) {
handle(err);
}
}
生命奔腾不息,技术更新不止,技术的一切更新难道不是更好的服务我们吗?
如果你还要对Generator有更深的了解,姑且移步至:
廖雪峰对Generator的总结
阮一峰对Generator的总结
async/wait
Generator函数是将函数分步骤阻塞,只有主动调用next() 才能进行下一步,async函数就相当于自执行的Generator函数,相当于自带一个状态机,在await的部分等待返回, 返回后自动执行下一步。
async/wait用法
网上有种说法,是烁async/wait是相当于Generate 把“*“变成了async 把 yield 变成了 await ???😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁😁
怎么说呢,既然这样说了,我认为还是有一定得道理的,但是不至于设计的初衷就是换了个写法,要不然ECMA那些专家岂不是那个地方有点疼吗😁😁
咱们用有个例子来展示async/wait的使用方法:
async function fun (x){
const a = await x + 1;
await a;
}
和Generator的异同
这里咱们可以看到,相比于Generator确实很像,但是有区别:
- 将*转为async,并且至于function最前
- 将yield转为awiat,并且不再return
- await后返回的是Promise对象,需要.then获取拿出,而Generator的return出具体的结果
刚刚说Generator把异步回调代码变成“同步”代码,天然的适合ajax请求,而async/wait作为Generator的语法糖,将这种“同步”发挥到了极致,在处理多个循环嵌套的时候,和Generator一样,将我们从回调的深渊中解救出来
写这边完整,查阅了很多的资料,我将下段代码直接贴出来,看到的仁兄不要介意,来展示一个Async函数的具体是怎么来处理这件事情的:
const fun1 = () => {
return new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve('fun1');
console.log('fun1');
},1000)
})
}
const fun2 = () => {
return new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve('fun2');
console.log('fun2');
},1000)
})
}
const fun3 = () => {
return new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve('fun3');
console.log('fun3');
},1000)
})
}
async function runAll () {
await fun1();
await fun2();
await fun3();
}
runAll().then()
.catch()
哇塞,看到这段代码,是不是再也没有那些令人恶心的循环嵌套,再也没有像Generator那种星号(*)都出来的奇葩写法,其实技术难道不和人一样,脱俗与新颖,而又终于平常,我们可以遇到的未来是async/wait必将在以后的开发中大放异彩,尽情的享受新技术带来的震撼吧
总结
关于异步处理,如果说ES5的回调使我们陷入地狱,ES6的Promise使我们脱离魔障,终于、ES7的async-await带我们走向光明
技术像时间的巨轮,永不停止的向前滚去,而我们要做的就是永葆一颗学习的心,去不断得探索,去学习,热爱自己的工作,不锲于自己的未来