js 異步的幾種解決方案

為什么會(huì)出現(xiàn)異步

js是一門為瀏覽器而誕生的語言,發(fā)展到現(xiàn)在,js已經(jīng)不僅僅只在瀏覽器上運(yùn)行了,服務(wù)端也可以運(yùn)行js,像node。而js最初設(shè)計(jì)是單線程,也就是說會(huì)一行一行的執(zhí)行,下面需要等待上面代碼執(zhí)行完畢,也就是說在特定的時(shí)刻只能做特定的事情,阻塞其他代碼的執(zhí)行。

常用的異步例如網(wǎng)絡(luò)請(qǐng)求、讀取文件等。

異步解決方案

了解javascript為什么會(huì)出現(xiàn)異步,那么我們?cè)撛趺慈ソ鉀Q異步呢?如何書寫日常工作中的工程代碼呢?javascript的演變中出現(xiàn)了如下幾種解決方案。

callback

一般在網(wǎng)絡(luò)請(qǐng)求中我們并不知道服務(wù)端啥時(shí)候返回結(jié)果,在這個(gè)等待的過程中,我們不能讓頁面一直卡頓或是不能操作的狀態(tài),這樣會(huì)給用戶很不好的體驗(yàn)感覺,我們又需要在服務(wù)端返回結(jié)果的時(shí)候來進(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)求的過程中,并不影響用戶對(duì)別的操作(除非不想讓用戶操作,必須要等待這個(gè)操作完成),當(dāng)服務(wù)端返回?cái)?shù)據(jù)時(shí),我們可以通過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è)問題。promise是在ES6中被統(tǒng)一規(guī)范,由瀏覽器直接支持,promise為一諾千金的意思,意思是在將來不管這個(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

我們希望以同步方式寫異步代碼,可以使邏輯清晰,代碼簡(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ù)沒有執(zhí)行,只是生成了一個(gè)genertor對(duì)象,函數(shù)屬于暫停狀態(tài),只有當(dāng)執(zhí)行.next()時(shí),才會(huì)激活暫停狀態(tà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)稱是異步的終極解決方案,讓我們以同步的方式來書寫異步代碼,這樣看起來更簡(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);

? ? ? ?}

? ? ?})

? })

}

以上就是封裝好的微信登錄過程中的獲取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的寫法類似,具備更好的語義,并且返回的是promise

作者:lzksdxh

鏈接:https://juejin.im/post/5af8f706f265da0b8f62a7d1

來源:掘金

著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 弄懂js異步 講異步之前,我們必須掌握一個(gè)基礎(chǔ)知識(shí)-event-loop。 我們知道JavaScript的一大特點(diǎn)...
    DCbryant閱讀 2,879評(píng)論 0 5
  • 異步編程對(duì)JavaScript語言太重要。Javascript語言的執(zhí)行環(huán)境是“單線程”的,如果沒有異步編程,根本...
    呼呼哥閱讀 7,404評(píng)論 5 22
  • Promise 對(duì)象 Promise 的含義 Promise 是異步編程的一種解決方案,比傳統(tǒng)的解決方案——回調(diào)函...
    neromous閱讀 8,832評(píng)論 1 56
  • 你不知道JS:異步 第三章:Promises 接上篇3-1 錯(cuò)誤處理(Error Handling) 在異步編程中...
    purple_force閱讀 1,494評(píng)論 0 2
  • 定好鬧鐘,明天要去上班了。
    百香小趣閱讀 1,234評(píng)論 0 49

友情鏈接更多精彩內(nèi)容