- Generator 函数需要手动通过返回值的 next 方法执行,而 async 函数自带执行器,执行方式和普通函数完全一样。
var result = asyncReadFiles(fileA, fileB, fileC);
-
语义明确,async 表示异步,await 表示后续表达式需要等待触发的异步操作结束
-
co 模块中 yield 后面只能跟一个 thunk 函数或 promise 对象,而 await 后面可以是任何类型(不是 Promise 对象就同步执行)
-
返回值是一个 Promise 对象,不是 Iterator ,比 Generator 方便
我们可以实现这样的一个 async 函数:
async function asyncFun(){
//code here
}
//equal to…
function asyncFun(args){
return fun(function*(){
//code here…
});
function fun(genF){
return new Promise(function(resolve, reject){
var gen = genF();
function step(nextF){
try{
var next = nextF();
} catch(e) {
return reject(e);
}
if(next.done){
return resolve(next.value);
}
Promise.resolve(next.value).then(function(data){
step(function(){ return gen.next(data); });
}, function(e){
step(function(){ return gen.throw(e); });
});
}
step(function() { return gen.next(undefined); });
});
}
}
我们使用 async 函数做点简单的事情:
function timeout(ms){
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}
async function delay(nap, …values){
while(1){
try{
await timeout(nap);
} catch(e) {
console.log(e);
}
var val = values.shift();
if(val)
console.log(val)
else
break;
}
}
delay(600,1,2,3,4); //每隔 600ms 输出一个数
这里需要注意:应该把后面跟 promise对象的 await 放在一个 try 中,防止其被 rejected。当然上面的 try 语句也可以这样写:
var ms = await timeout(nap).catch((e) => console.log(e));
对于函数参数中的回调函数不建议使用,避免出现不应该的错误
//反例: 会得到错误结果
async function fun(db){
let docs = [{},{},{}];
docs.forEach(async function(doc){ //ReferenceError: Invalid left-hand side in assignment
await db.post(doc);
});
}
//改写, 但依然顺序执行
async function fun(db){
let docs = [{},{},{}];
for(let doc of docs){
await db.post(doc);
}
}
//改写, 并发执行
async function fun(db){
let docs = [{},{},{}];
let promises = docs.map((doc) => db.post(doc));
let result = await Promise.all(promises)
console.log(result);
}
//改写, 并发执行
async function fun(db){
let docs = [{},{},{}];
let promises = docs.map((doc) => db.post(doc));
let result = [];
for(let promise of promises){
result.push(await promise);
}
console.log(result);
}
Promise,Generator 和 async 函数比较
这里我们实现一个简单的功能,可以直观的比较一下。实现如下功能:
在一个 DOM 元素上绑定一系列动画,每一个动画完成才开始下一个,如果某个动画执行失败,返回最后一个执行成功的动画的返回值
- Promise 方法
function chainAnimationPromise(ele, animations){
var ret = null; //存放上一个动画的返回值
var p = Promise.resolve();
for(let anim of animations){
p = p.then(function(val){
ret = val;
return anim(ele);
});
}
return p.catch(function(e){
/忽略错误/
}).then(function(){
return ret; //返回最后一个执行成功的动画的返回值
});
}
- Generator 方法
function chainAnimationGenerator(ele, animations){
return fun(function*(){
var ret = null;
try{
for(let anim of animations){
ret = yield anim(ele);
}
} catch(e) {
/忽略错误/
}
return ret;
});
function fun(genF){
return new Promise(function(resolve, reject){
var gen = genF();
function step(nextF){
try{
var next = nextF();
} catch(e) {
return reject(e);
}
if(next.done){
return resolve(next.value);
}
Promise.resolve(next.value).then(function(data){
step(function(){ return gen.next(data); });
}, function(e){
step(function(){ return gen.throw(e); });
});
}
step(function() { return gen.next(undefined); });
});
}
}
- async 函数方法
async function chainAnimationAsync(ele, animations){
var ret = null;
try{
for(let anim of animations){
ret = await anim(elem);
}
} catch(e){
/忽略错误/
}
return ret;
}
一个经典题
console.log(0);
setTimeout(function(){
console.log(1)
},0);
setTimeout(function(){
console.log(2);
},1000);
var pro = new Promise(function(resolve, reject){
console.log(3);
resolve();
}).then(resolve => console.log(4));
console.log(5);
setTimeout(function(){
console.log(6)
},0);
pro.then(resolve => console.log(7));
var pro2 = new Promise(function(resolve, reject){
console.log(8);
resolve(10);
}).then(resolve => console.log(11))
.then(resolve => console.log(12))
.then(resolve => console.log(13));
console.log(14);
// 0 3 5 8 14 4 11 7 12 13 1 6 2
小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Web前端开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注:前端)
css
1,盒模型
2,如何实现一个最大的正方形
3,一行水平居中,多行居左
4,水平垂直居中
5,两栏布局,左边固定,右边自适应,左右不重叠
6,如何实现左右等高布局
7,画三角形
8,link @import导入css
9,BFC理解
js
1,判断 js 类型的方式
2,ES5 和 ES6 分别几种方式声明变量
3,闭包的概念?优缺点?
4,浅拷贝和深拷贝
5,数组去重的方法
6,DOM 事件有哪些阶段?谈谈对事件代理的理解
7,js 执行机制、事件循环
8,介绍下 promise.all
9,async 和 await,
10,ES6 的 class 和构造函数的区别
11,transform、translate、transition 分别是什么属性?CSS 中常用的实现动画方式,
12,介绍一下rAF(requestAnimationFrame)
13,javascript 的垃圾回收机制讲一下,
14,对前端性能优化有什么了解?一般都通过那几个方面去优化的?
垂直居中
5,两栏布局,左边固定,右边自适应,左右不重叠
6,如何实现左右等高布局
7,画三角形
8,link @import导入css
9,BFC理解
[外链图片转存中…(img-w11EMrvQ-1710592693645)]
js
1,判断 js 类型的方式
2,ES5 和 ES6 分别几种方式声明变量
3,闭包的概念?优缺点?
4,浅拷贝和深拷贝
5,数组去重的方法
6,DOM 事件有哪些阶段?谈谈对事件代理的理解
7,js 执行机制、事件循环
8,介绍下 promise.all
9,async 和 await,
10,ES6 的 class 和构造函数的区别
11,transform、translate、transition 分别是什么属性?CSS 中常用的实现动画方式,
12,介绍一下rAF(requestAnimationFrame)
13,javascript 的垃圾回收机制讲一下,
14,对前端性能优化有什么了解?一般都通过那几个方面去优化的?
[外链图片转存中…(img-c1t8zKzU-1710592693645)]