JavaScript-异步编程

72次阅读

共计 5400 个字符,预计需要花费 14 分钟才能阅读完成。

Callback

场景一

在微信小程序中,我们对请求做了一层封装,如果请求时,检测到没有 token 或者token 已过期,则需要重新调用 刷新 token 方法,更新 token 后再去请求,然而我们打开微信小程序首页,此时可能并发多个请求,就会出现多次请求刷新 token 方法,我们 需求 是:在第一个请求刷新 token 后再执行后面的业务请求

模拟代码:

function requestA(){setTimeout(()=>{console.log('requestA')
},1000)
}
function requestB(){setTimeout(()=>{console.log('requestB')
},800)
}
function requestC(){setTimeout(()=>{console.log('requestC')
},600)
}
function requestD(){setTimeout(()=>{console.log('requestD')
},400)
}
function requestE(){setTimeout(()=>{console.log('requestE')
},200)
}

requestA 改造:

// 对 requestA 进行 回调 改变
function requestA(callback){setTimeout(()=>{console.log('requestA')
callback && callback()},1000)
}

执行:

requestA(()=>{requestB()
requestC()
requestD()
requestE()})

场景二:

多个请求逐层向上依赖上个请求的数据

示例:

function requestA(callback){setTimeout(()=>{callback && callback('requestA 请求的结果')
},1000)
}
function requestB(ret,callback){if(ret === 'requestA 请求的结果'){setTimeout(()=>{callback && callback('requestB 请求的结果')
},800)
}
}
function requestC(ret,callback){if(ret === 'requestB 请求的结果'){setTimeout(()=>{callback && callback('requestC 请求的结果')
},600)
}
}
function requestD(ret,callback){if(ret === 'requestC 请求的结果'){setTimeout(()=>{callback && callback('requestD 请求的结果')
},400)
}
}
function requestE(ret,callback){if(ret === 'requestD 请求的结果'){setTimeout(()=>{callback && callback('requestE 请求的结果')
},200)
}
}

执行:

requestA(ret=>{console.log(ret)
requestB('requestA 请求的结果',ret=>{console.log(ret)
requestC('requestB 请求的结果',ret=>{console.log(ret)
requestD('requestC 请求的结果',ret=>{console.log(ret)
requestE('requestD 请求的结果',ret=>{console.log(ret)
})
})
})
})
})

依次打印出了:

requestA 请求的结果 ->requestB 请求的结果 ->requestC 请求的结果 ->requestD 请求的结果 ->requestE 请求的结果

Promise

场景:多个请求逐层向上依赖上个请求的数据,用 promise 改造

function requestA(){return new Promise((resolve,reject)=>{setTimeout(()=>{resolve('requestA 请求的结果')
},1000)
})
}
function requestB(param){return new Promise((resolve,reject)=>{if(param==='requestA 请求的结果'){setTimeout(()=>{resolve('requestB 请求的结果')
},800)
}else{reject('requestB 请求失败')
}
})
}
function requestC(param){return new Promise((resolve,reject)=>{if(param==='requestB 请求的结果'){setTimeout(()=>{resolve('requestC 请求的结果')
},600)
}else{reject('requestC 请求失败')
}
})
}
function requestD(param){return new Promise((resolve,reject)=>{if(param==='requestC 请求的结果'){setTimeout(()=>{resolve('requestD 请求的结果')
},400)
}else{reject('requestD 请求失败')
}
})
}
function requestE(param){return new Promise((resolve,reject)=>{if(param==='requestD 请求的结果'){setTimeout(()=>{resolve('requestE 请求的结果')
},200)
}else{reject('requestE 请求失败')
}
})
}

使用:

requestA()
.then(ret=>requestB(ret))
.then(ret=>requestC(ret))
.then(ret=>requestD(ret))
.then(ret=>requestE(ret))
.then(ret=>{console.log(ret)//requestE 请求的结果
}).catch(err=>{console.log(err)
})

Generator

模拟请求:

function requestA(){return new Promise((resolve,reject)=>{setTimeout(()=>{resolve('requestA 请求的结果')
},1000)
})
}
function requestB(param){return new Promise((resolve,reject)=>{if(param==='requestA 请求的结果'){setTimeout(()=>{resolve('requestB 请求的结果')
},800)
}else{reject('requestB 请求失败')
}
})
}
function requestC(param){return new Promise((resolve,reject)=>{if(param==='requestB 请求的结果'){setTimeout(()=>{resolve('requestC 请求的结果')
},600)
}else{reject('requestC 请求失败')
}
})
}
function requestD(param){return new Promise((resolve,reject)=>{if(param==='requestC 请求的结果'){setTimeout(()=>{resolve('requestD 请求的结果')
},400)
}else{reject('requestD 请求失败')
}
})
}
function requestE(param){return new Promise((resolve,reject)=>{if(param==='requestD 请求的结果'){setTimeout(()=>{resolve('requestE 请求的结果')
},200)
}else{reject('requestE 请求失败')
}
})
}

Generator的异步使用:

function* gen(){let result = yield requestA();
// console.log(result+'result')
let result1 = yield requestB(result);
// console.log(result1+'result1')
let result2 = yield requestC(result1);
// console.log(result2+'result2')
let result3 = yield requestD(result2);
// console.log(result3+'result3')
let result4 = yield requestE(result3);
// console.log(result4+'result4')
return result4
}
var g = gen();
var result = g.next();
result.value.then(function(data){console.log(data+'requestA 请求的数据')
return g.next(data).value
}).then(function(data){console.log(data+'requestB 请求的数据')
return g.next(data).value
}).then(function(data){console.log(data+'requestC 请求的数据')
return g.next(data).value
}).then(function(data){console.log(data+'requestD 请求的数据')
return g.next(data).value
}).then(function(data){console.log(data+'requestE 请求的数据')
})

Async

模拟请求:

function requestA(){return new Promise((resolve,reject)=>{setTimeout(()=>{resolve('requestA 请求的结果')
},1000)
})
}
function requestB(param){return new Promise((resolve,reject)=>{if(param==='requestA 请求的结果'){setTimeout(()=>{resolve('requestB 请求的结果')
},800)
}else{reject('requestB 请求失败')
}
})
}
function requestC(param){return new Promise((resolve,reject)=>{if(param==='requestB 请求的结果'){setTimeout(()=>{resolve('requestC 请求的结果')
},600)
}else{reject('requestC 请求失败')
}
})
}
function requestD(param){return new Promise((resolve,reject)=>{if(param==='requestC 请求的结果'){setTimeout(()=>{resolve('requestD 请求的结果')
},400)
}else{reject('requestD 请求失败')
}
})
}
function requestE(param){return new Promise((resolve,reject)=>{if(param==='requestD 请求的结果'){setTimeout(()=>{resolve('requestE 请求的结果')
},200)
}else{reject('requestE 请求失败')
}
})
}

Async的异步使用:

async function init(){let ret1 =await requestA()
let ret2 =await requestB(ret1)
let ret3 =await requestC(ret2)
let ret4 =await requestD(ret3)
let ret5 =await requestE(ret4)
return ret5
}
init().then(res=>{console.log(res)//requestE 请求的结果
}).catch(err=>{console.log(err)
})

事件监听

脚本的执行不取决代码的顺序,而取决于某一个事件是否发生。

案列:

$(document).ready(function(){console.log('DOM 已经 ready')
});

发布 / 订阅

发布 / 订阅模式是利用一个消息中心,发布者发布一个消息给消息中心,订阅者从消息中心订阅该消息

案例:

// 订阅 done 事件
$('#box').on('done',function(data){console.log(data)
})
// 发布事件
$('#box').trigger('done,'data')

正文完
 0