為什么會(huì)出現(xiàn)異步
js是一門(mén)為瀏覽器而誕生的語(yǔ)言,發(fā)展到現(xiàn)在壶谒,js已經(jīng)不僅僅只在瀏覽器上運(yùn)行了仆救,服務(wù)端也可以運(yùn)行js抒和,像node。而js最初設(shè)計(jì)是單線程彤蔽,也就是說(shuō)會(huì)一行一行的執(zhí)行摧莽,下面需要等待上面代碼執(zhí)行完畢,也就是說(shuō)在特定的時(shí)刻只能做特定的事情顿痪,阻塞其他代碼的執(zhí)行镊辕。
常用的異步例如網(wǎng)絡(luò)請(qǐng)求、讀取文件等蚁袭。
異步解決方案
了解javascript為什么會(huì)出現(xiàn)異步征懈,那么我們?cè)撛趺慈ソ鉀Q異步呢?如何書(shū)寫(xiě)日常工作中的工程代碼呢揩悄?javascript的演變中出現(xiàn)了如下幾種解決方案卖哎。
callback
一般在網(wǎng)絡(luò)請(qǐng)求中我們并不知道服務(wù)端啥時(shí)候返回結(jié)果,在這個(gè)等待的過(guò)程中删性,我們不能讓頁(yè)面一直卡頓或是不能操作的狀態(tài)亏娜,這樣會(huì)給用戶很不好的體驗(yàn)感覺(jué),我們又需要在服務(wù)端返回結(jié)果的時(shí)候來(lái)進(jìn)行相應(yīng)的操作或是數(shù)據(jù)更新镇匀。于是回調(diào)函數(shù)就成為異步的第一個(gè)解決方案照藻,如下:
$.ajax({
? ? "url": "",
? ? success: function(data){
? ? ?//函數(shù)返回成功需要進(jìn)行的操作或數(shù)據(jù)更新
? ? },
? ? error: function(err){
? ? //函數(shù)返回失敗需要進(jìn)行的操作或提示
? ?}
})
這是在jq中我們非常熟悉的一個(gè)操作,當(dāng)我們?nèi)フ?qǐng)求服務(wù)端時(shí)汗侵,不管成功或失敗幸缕,服務(wù)端都會(huì)返回一個(gè)結(jié)果群发,success和error函數(shù)就是一個(gè)callback函數(shù),不管成功或是失敗发乔,我們都能進(jìn)行相應(yīng)的操作或是提示熟妓,在網(wǎng)絡(luò)請(qǐng)求的過(guò)程中,并不影響用戶對(duì)別的操作(除非不想讓用戶操作栏尚,必須要等待這個(gè)操作完成)起愈,當(dāng)服務(wù)端返回?cái)?shù)據(jù)時(shí),我們可以通過(guò)callback接收到译仗,這個(gè)時(shí)候我們?cè)龠M(jìn)行相應(yīng)的操作抬虽。
Promise
在callback中,如果當(dāng)前網(wǎng)絡(luò)請(qǐng)求需要依賴前一個(gè)網(wǎng)絡(luò)請(qǐng)求纵菌,我們就有可能掉進(jìn)回調(diào)地獄阐污,
如圖:
于是promise的出現(xiàn)為我們解決了這個(gè)問(wèn)題。promise是在ES6中被統(tǒng)一規(guī)范,由瀏覽器直接支持,promise為一諾千金的意思咱圆,意思是在將來(lái)不管這個(gè)狀態(tài)成功或是失敗笛辟,都將返回一個(gè)結(jié)果。
promise有三種狀態(tài):
等待中? pending序苏;
已完成? fulfilled手幢;
已拒絕? reject;
let test = new promise(resolve,reject){
? ? ? if(success){
? ? ? ? ?resolve();
? ? ? }else{
? ? ? ? reject();
? ? ? }
? }
test()
.then(res => {
? ?//成功時(shí)返回函數(shù)
})
.catch(err => {
? //失敗時(shí)返回函數(shù)
})
Generator
我們希望以同步方式寫(xiě)異步代碼忱详,可以使邏輯清晰围来,代碼簡(jiǎn)潔,為了實(shí)現(xiàn)這種目的踱阿,我們又演進(jìn)出generator方案管钳,
function * add(x){
? ?yield? x + 50;
? ?yield x + 100;
? ?return x + 150;
}
let? test = add(5);
test.next(); //done: true , value: 55
test.next(); //done: true , value: 105
test.next(); //done: true , value: 155
如上钦铁,genertor與普通函數(shù)區(qū)別不大软舌,function后面加了一個(gè)*,
首先定義了一個(gè)test = add(5),函數(shù)沒(méi)有執(zhí)行牛曹,只是生成了一個(gè)genertor對(duì)象佛点,函數(shù)屬于暫停狀態(tài),只有當(dāng)執(zhí)行.next()時(shí)黎比,才會(huì)激活暫停狀態(tài)超营,開(kāi)始執(zhí)行內(nèi)部代碼,遇到第一個(gè)yield才會(huì)返回執(zhí)行結(jié)果阅虫,并記住上下文演闭,暫停,交出控制權(quán)颓帝,再次執(zhí)行米碰,找到第二個(gè)yield窝革,并重復(fù)上述步驟
function* Fn(){
? var result = yield ajax(url);
var result1 = yield ajax(url1);
}
let F = Fn();
var result = F.next();
result.value
.then(res => {
? ?F.next();
})
.catch(err => {
})
如上 封裝一個(gè)ajax異步吕座,定義一個(gè)genertor對(duì)象虐译,執(zhí)行請(qǐng)求交出控制權(quán),根據(jù)返回結(jié)果執(zhí)行第二個(gè)ajax請(qǐng)求
asnyc/await
ES7的asnyc/await號(hào)稱是異步的終極解決方案吴趴,讓我們以同步的方式來(lái)書(shū)寫(xiě)異步代碼漆诽,這樣看起來(lái)更簡(jiǎn)潔,邏輯更清晰锣枝。
比如微信小程序煩人的異步:
const Login =? data => {?
? return new Promise( (resolve, reject) => {?
? ? wx.login({?
? ? ? success: res => {?
? ? ? ? ?resolve(res);
? ? ? ?},?
? ? ? ?fail: err => {??
? ? ? ? ? reject(err);?
? ? ? ? }?
? ? ? })?
? ?})?
}
const getUserInfos = data => {
? return new Promise((resolve,reject){
? ? wx.getUserInfo({
success: res => {
? ? ? ?resolve(res);
? ? ? },
? ? ?fail: err => {?
? ? ? ?reject(err);
? ? ?}?
? ? })
? })
}
const sendCode = data = > {
? return new Promise((resolve,reject){
? ? ?wx.request({
? ? ? ?url: '',
? ? ? ?success: res=> {
? ? ? ? ? ?resolve(res);
? ? ? ?},
? ? ? ?fail: err => {
? ? ? ? ? reject(err);
? ? ? ?}
? ? ?})
? })
}
以上就是封裝好的微信登錄過(guò)程中的獲取code userInfo 和發(fā)送ajax請(qǐng)求的幾個(gè)函數(shù)厢拭,
然后
asycn function getLogin(){
?try {
? let result_login? =? await Login();
? let result_userInfo = await getUserInfos();
result_userInfo['code'] = result_login['code'];
? let result_sendCode = await sendCode(result_userInfo );
? return result_sendCode;
?}catch(err){
?console.log(err);
}
}
getLogin()
.then(res => {
})
.catch(err => {
}
async與genertor的寫(xiě)法類似,具備更好的語(yǔ)義撇叁,并且返回的是promise
作者:lzksdxh
鏈接:https://juejin.im/post/5af8f706f265da0b8f62a7d1
來(lái)源:掘金
著作權(quán)歸作者所有蚪腐。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處税朴。