摘要:?jiǎn)栴}前端小同學(xué)在做頁(yè)面的時(shí)候,犯了個(gè)常見(jiàn)的錯(cuò)誤把多個(gè)請(qǐng)求順序著寫(xiě)下來(lái)了,而后面的請(qǐng)求,對(duì)前面請(qǐng)求的返回結(jié)果,是有依賴的。經(jīng)提醒,發(fā)現(xiàn)從版開(kāi)始,返回的就是對(duì)象了,那么函數(shù)可以直接返回的返回值
問(wèn)題
前端小同學(xué)在做頁(yè)面的時(shí)候,犯了個(gè)常見(jiàn)的錯(cuò)誤:把多個(gè)Ajax請(qǐng)求順序著寫(xiě)下來(lái)了,而后面的請(qǐng)求,對(duì)前面請(qǐng)求的返回結(jié)果,是有依賴的。如下面的代碼所示:
var someData; $.ajax({ url: "/prefix/entity1/action1", type: "GET" , async: true, contentType: "application/json", success: function (resp) { //do something on response someData.attr1 = resp.attr1; }, error: function (XMLHttpRequest, textStatus, errorThrown) { //在這個(gè)頁(yè)面里,所有的請(qǐng)求的錯(cuò)誤都做同樣的處理 if (XMLHttpRequest.status == "401") { window.location.href = "/login.html"; } else { alert(XMLHttpRequest.responseText); } } }); $.ajax({ url: "/prefix/entity2/action2", type: "POST" , dataType: "json", data: JSON.stringify(someData), async: true, contentType: "application/json", success: function (resp) { //do something on response }, error: function (XMLHttpRequest, textStatus, errorThrown) { //在這個(gè)頁(yè)面里,所有的請(qǐng)求的錯(cuò)誤都做同樣的處理 if (XMLHttpRequest.status == "401") { window.location.href = "/login.html"; } else { alert(XMLHttpRequest.responseText); } } });
以上代碼有兩個(gè)問(wèn)題:
*首先就是執(zhí)行順序不能保證,action2很可能在action1返回之前就發(fā)出了,導(dǎo)致someData.attr1這個(gè)參數(shù)沒(méi)能正確傳出
*其次兩個(gè)ajax請(qǐng)求的代碼重復(fù)很嚴(yán)重
代碼重復(fù)的問(wèn)題相對(duì)好解決,尤其是在自己的項(xiàng)目里,各種參數(shù)可以通過(guò)規(guī)范定死,封裝一個(gè)參數(shù)更少的ajax方法就好了
//url:地址 //data:數(shù)據(jù)對(duì)象,在函數(shù)內(nèi)部會(huì)轉(zhuǎn)化成json串,如果沒(méi)傳,表示用GET方法,如果傳了,表示用POST方法 function ajax(url, data, callback) { $.ajax({ url: url, type: data == null ? "GET" : "POST", dataType: "json", data: data == null ? "" : JSON.stringify(data), async: true, contentType: "application/json", success: function (resp) { callback(resp); }, error: function (XMLHttpRequest, textStatus, errorThrown) { if (XMLHttpRequest.status == "401") { window.parent.location = "/enterprise/enterprise_login.html"; self.location = "/enterprise/enterprise_login.html"; } else { alert(XMLHttpRequest.responseText); } } }); }
這樣只有url,data和callback三個(gè)必要的參數(shù)要填,其他都定死了
執(zhí)行順序的問(wèn)題,可以把第二個(gè)請(qǐng)求放在第一個(gè)請(qǐng)求的回調(diào)里,形如:
ajax("/prefix/entity1/action1",null, function(resp){ //do something on response someData.attr1 = resp.attr1; ajax("/prefix/entity2/action2", someData, function(resp){ //do something on response } };
至此問(wèn)題似乎解決得很完美,但可以想見(jiàn),如果請(qǐng)求不止兩個(gè),而是4、5個(gè),同時(shí)還有其他異步操作(比如我們的頁(yè)面里有Vue對(duì)象的初始化),相互之間有依賴關(guān)系,光是這樣層層疊疊的括號(hào)嵌套,就已經(jīng)讓人頭暈了。
需要找到一種方法,讓異步調(diào)用的表達(dá)看起來(lái)像同步調(diào)用一樣。
正好最近看了阮一峰老師關(guān)于ES6的書(shū),而且用戶也沒(méi)有強(qiáng)硬要求兼容IE瀏覽器,于是就選擇了Promise的方案
解決方案引入Promise
其實(shí)現(xiàn)代瀏覽器都已經(jīng)內(nèi)置支持了Promise,連第三方庫(kù)都不需要了,只有IE不行,放棄了
改造ajax封裝函數(shù),在成功的時(shí)候調(diào)用resolve(),失敗的時(shí)候調(diào)用reject(),并且返回Promise對(duì)象
function ajax(url, data, callback) { var p = new Promise(function (resolve, reject) { $.ajax({ url: url, type: data == null ? "GET" : "POST", dataType: "json", data: data == null ? "" : JSON.stringify(data), async: true, contentType: "application/json", success: function (resp) { callback(resp); resolve(); }, error: function (XMLHttpRequest, textStatus, errorThrown) { if (XMLHttpRequest.status == "401") { window.parent.location = "/enterprise/enterprise_login.html"; self.location = "/enterprise/enterprise_login.html"; } else { alert(XMLHttpRequest.responseText); } reject(); } }); }); return p; }
修改調(diào)用端
ajax("/prefix/entity1/action1",null, function(resp){ //do something on response someData.attr1 = resp.attr1; }).then( ajax("/prefix/entity2/action2", someData, function(resp){ //do something on response } ).then( initVue() ; ).then( //do something else )
至此完美解決。
經(jīng)@miroki 提醒,發(fā)現(xiàn)Jquery從1.5版開(kāi)始,返回的就是thenable對(duì)象了,那么ajax函數(shù)可以直接返回$.ajax()的返回值
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/81769.html
摘要:引擎線程也稱為內(nèi)核,負(fù)責(zé)處理腳本程序例如引擎引擎線程負(fù)責(zé)解析腳本,運(yùn)行代碼。對(duì)象代表一個(gè)未完成但預(yù)計(jì)將來(lái)會(huì)完成的操作。注意一旦新建就會(huì)立即執(zhí)行它屬于,無(wú)法取消。 寫(xiě)在前面: 第一遍學(xué)Promise時(shí), 只是大概過(guò)了一遍, 感覺(jué)學(xué)的不夠深入, 這一篇算是對(duì)之前的一個(gè)總結(jié)吧. Promise在ES6中也屬于一個(gè)較難理解的一部分; 所以在學(xué)習(xí)一個(gè)比較難理解的知識(shí)點(diǎn)時(shí), 我們可以圍繞這個(gè)知識(shí)點(diǎn)...
摘要:簽訂協(xié)議的兩方分別是異步接口和。在異步函數(shù)中,使用異常捕獲的方案,代替了的異常捕獲的方案。需要注意的是,在異步函數(shù)中使異步函數(shù)用時(shí)要使用,不然異步函會(huì)被同步執(zhí)行。 同步與異步 通常,代碼是由上往下依次執(zhí)行的。如果有多個(gè)任務(wù),就必需排隊(duì),前一個(gè)任務(wù)完成,后一個(gè)任務(wù)才會(huì)執(zhí)行。這種執(zhí)行模式稱之為: 同步(synchronous) 。新手容易把計(jì)算機(jī)用語(yǔ)中的同步,和日常用語(yǔ)中的同步弄混淆。如,...
摘要:從源碼看概念與實(shí)現(xiàn)是異步編程中的重要概念,它較好地解決了異步任務(wù)中回調(diào)嵌套的問(wèn)題。這些概念中有趣的地方在于,標(biāo)識(shí)狀態(tài)的變量如都是形容詞,用于傳入數(shù)據(jù)的接口如與都是動(dòng)詞,而用于傳入回調(diào)函數(shù)的接口如及則在語(yǔ)義上用于修飾動(dòng)詞的副詞。 從源碼看 Promise 概念與實(shí)現(xiàn) Promise 是 JS 異步編程中的重要概念,它較好地解決了異步任務(wù)中回調(diào)嵌套的問(wèn)題。在沒(méi)有引入新的語(yǔ)言機(jī)制的前提下,這...
摘要:異步請(qǐng)求線程在在連接后是通過(guò)瀏覽器新開(kāi)一個(gè)線程請(qǐng)求將檢測(cè)到狀態(tài)變更時(shí),如果設(shè)置有回調(diào)函數(shù),異步線程就產(chǎn)生狀態(tài)變更事件,將這個(gè)回調(diào)再放入事件循環(huán)隊(duì)列中。 基礎(chǔ):瀏覽器 -- 多進(jìn)程,每個(gè)tab頁(yè)獨(dú)立一個(gè)瀏覽器渲染進(jìn)程(瀏覽器內(nèi)核) 每個(gè)瀏覽器渲染進(jìn)程是多線程的,主要包括:GUI渲染線程 JS引擎線程 也稱為JS內(nèi)核,負(fù)責(zé)處理Javascript腳本程序。(例如V8引擎) JS引擎線程負(fù)...
摘要:能幫我們解決什么痛點(diǎn)實(shí)現(xiàn)異步執(zhí)行,在未出現(xiàn)前,我們通常是使用嵌套的回調(diào)函數(shù)來(lái)解決的。那么,接下來(lái)我們看一下使用的實(shí)例可以傳入兩個(gè)參數(shù)表示兩個(gè)狀態(tài)的回調(diào)函數(shù),第一個(gè)是,必選參數(shù)第二個(gè)是,可選參數(shù)的方便之處。 深入理解promise 對(duì)于現(xiàn)在的前端同學(xué)來(lái)說(shuō)你不同promise你都不好意思出門了。對(duì)于前端同學(xué)來(lái)說(shuō)promise已經(jīng)成為了我們的必備技能。 那么,下面我們就來(lái)說(shuō)一說(shuō)promise...
閱讀 3069·2021-09-28 09:43
閱讀 902·2021-09-08 09:35
閱讀 1441·2019-08-30 15:56
閱讀 1183·2019-08-30 13:00
閱讀 2732·2019-08-29 18:35
閱讀 1829·2019-08-29 14:07
閱讀 3432·2019-08-29 13:13
閱讀 1333·2019-08-29 12:40