在工作当中,最常使用的js中的异步变成有一下几类:
- 回调函数
最突出的例子为setTimeout
console.log("aaa");
setTimeout(function(){
console.log("bb")
},3000);
console.log("ccc");
- ajax请求
- 事件监听
不因为代码的顺序而也决定是否执行,而是对动作进行监听,触发时才执行 - 观察者模式(发布/订阅)
对某一动作信号进行订阅,当信号发布时才进行触发
ES6中的异步解决:
Promise
- 让异步操作如同同步操作进行执行
- 创建即执行
- 不受外部影响,状态改变后不再变更
标准结构
const promise=new Promise(function(resolve,reject){
...code
if(成功){
resolve(a);
}else{//失败
reject(e);
}
});
promise.then(function(a){
//成功的回调
},function(e){
//失败的回调
});
Generator
1.暂停标志yield 使得generator函数可暂时将执行权力交由其他任
2.使用.next()方法既可以将执行权力再交还给generator行数
3.这样就完成了一步操作,结合promise可完成自动流程管理
function* gen(x){
let a=yield x+1;
let b=yield a+3;
return b;
}
let g=gen(1);
g.next(); //{value: 2, done: false}
g.next(3); //{value: 6, done: false}
g.next(); //{value: undefined, done: true}
var p=function (a){
return new Promise(function (resolve,reject){
//ajax code...{
resolve(data);
}
})
}
var gen=function* (x){
let a=yield p(x);
let b=yield p(a);
return b;
}
//方案一
var g=gen(xxx);
g.next().value.then(function(data){
g.next(data).value.then(function(data){
g.next(data);
})
})
//方案二
function selfrun(gen){
var g=gen();
function next(data){
var r=g.next(data);
if(r.done){
return r.value;
}else{
r.value.then(function(data){
next(data);
})
}
}
next();
}
selfrun(gen);
4.若执行较为麻烦,即可使用co模块
co(gen); //即可
async (generator+自动执行器)
1.如普通函数一样进行调用
2.调用后自动执行,标志await来进行停顿,在执行完await后面的表达式后再进行下面的操作
3.await返回一个promise,若出现reject则会被catch捕获,并且退出该方法,后面不执行
async function sleep(time){
await new Promise(resolve=>{
setTimeout(resolve,time);
})
}
async function asyncfun(){
for(let i=0;i<3;i++){
try{
await sleep(3000);
console.log(i);
}catch(e){}
}
}
asyncfun();
4.上面的例子是继发操作,按顺序依次执行,若有并发操作
//继发
await aa();
await bb();
//并发
//方式一
await Promise.all([aa(),bb()]);
//方式二
let a=aa();
let b=bb();
await a;
await b;
//方式三
for(let i if A){
await i.aa();
}
//并发发出请求
async function A(a){
//并发获取
const U=a.map(async u=>{
const u1=await ajaxU(u);
return u1;
})
for (const uu of U){
await uu;
console.log(uu)
}
}