摘要:簡(jiǎn)要說(shuō)明前面我寫了一篇方法封裝及文件設(shè)計(jì)文檔,主要用來(lái)說(shuō)明我們?cè)陧?xiàng)目中通常會(huì)對(duì)的方法進(jìn)行進(jìn)一步的封裝處理,便于我們?cè)跇I(yè)務(wù)代碼中使用。這篇文檔我們主要對(duì)封裝的方法進(jìn)行一個(gè)簡(jiǎn)要說(shuō)明。
簡(jiǎn)要說(shuō)明
前面我寫了一篇《jquery ajax 方法封裝及 api 文件設(shè)計(jì)》文檔,主要用來(lái)說(shuō)明我們?cè)陧?xiàng)目中通常會(huì)對(duì) jquery 的 ajax 方法進(jìn)行進(jìn)一步的封裝處理,便于我們?cè)跇I(yè)務(wù)代碼中使用。從那篇文檔中我們可以了解到如何封裝ajax方法、如何設(shè)計(jì) API 文件,以及如何在業(yè)務(wù)代碼中調(diào)用 API 接口。
這篇文檔我們主要對(duì)封裝的 ajax 方法進(jìn)行一個(gè)簡(jiǎn)要說(shuō)明。這里的封裝主要是將 $.ajax() 返回的 jqXHR 對(duì)象,通過(guò)調(diào)用 jQuery.Deferred() 方法創(chuàng)建成一個(gè)可鏈?zhǔn)秸{(diào)用的工具對(duì)象(其實(shí) jqXHR 本身就是 Deferred 對(duì)象,本來(lái)就可以進(jìn)行鏈?zhǔn)秸{(diào)用,后面會(huì)對(duì)此進(jìn)行說(shuō)明)。這樣我們就可以使用下面這種形式進(jìn)行鏈?zhǔn)秸{(diào)用:
// 鏈?zhǔn)秸{(diào)用 absService.getAbsListData(conditionObj) .done(function (result) { var data = ts.handleData(result); ts.render(data, columnChange); }) .fail(function (err, jqXHR) { Util.hideLoading("#abs-all-container"); });
同時(shí),通過(guò)一些處理,也允許調(diào)用者使用如下形式進(jìn)行調(diào)用:
// 傳入成功回調(diào)、失敗回調(diào) absService.getAbsListData(conditionObj, function (result) { var data = ts.handleData(result); ts.render(data, columnChange); }, function (err, jqXHR) { Util.hideLoading("#abs-all-container"); });
實(shí)際上,從 jQuery 1.5 開始,$.ajax() 返回的 jqXHR 對(duì)象就已經(jīng)實(shí)現(xiàn)了 Promise 接口, 使它擁有了 Promise 的所有屬性,方法和行為。也就是說(shuō) $.ajax() 返回的 jqXHR 對(duì)象本身就可以使用如下形式的調(diào)用:
$.ajax(options) .done(function (result, textStatus, jqXHR) { if (requestId === requestIdentifier[serviceName]) { ajaxRequest.ajax.handleResponse(result, $dfd, jqXHR, userOptions, serviceName, requestId); } }) .fail(function (jqXHR, textStatus, errorThrown) { if (requestId === requestIdentifier[serviceName]) { //jqXHR.status $dfd.reject.apply(this, arguments); userOptions.error.apply(this, arguments); } });
既然已經(jīng)可以使用這種方式使用 jqXHR對(duì)象,那為什么不直接將 jqXHR對(duì)象返回,然后在業(yè)務(wù)代碼中直接使用 jqXHR.done() 和 jqXHR.fail() 方法呢?為什么還要進(jìn)一步將其包裝成一個(gè)新的 Deferred 對(duì)象呢?
答:是為了在成功和失敗回調(diào)調(diào)用之前做一些統(tǒng)一的處理,比如對(duì)接口返回的數(shù)據(jù)進(jìn)行判斷、對(duì)返回的 JSON 字符串進(jìn)行解析、在請(qǐng)求失敗時(shí)輸出方法名和錯(cuò)誤信息等,我們把這些每次接口調(diào)用都會(huì)進(jìn)行的操作進(jìn)行統(tǒng)一處理,實(shí)現(xiàn)代碼復(fù)用,這樣業(yè)務(wù)代碼中就只需要關(guān)注拿到數(shù)據(jù)后的處理邏輯即可。
這些統(tǒng)一進(jìn)行的操作,我們放在 $.ajax().done() 和 $.ajax().fail() 方法中去執(zhí)行,然后將 $.ajax() 返回的 jqXHR對(duì)象包裝成新的 Deferred 對(duì)象,這樣就可以在業(yè)務(wù)代碼中通過(guò)鏈?zhǔn)秸{(diào)用做進(jìn)一步的處理,比如刷新表格內(nèi)容、更新頁(yè)面動(dòng)態(tài)等等。
代碼解讀/** * 封裝 jquery ajax * 例如: * ajaxRequest.ajax.triggerService( * "apiCommand", [命令數(shù)據(jù)] ) * .then(successCallback, failureCallback); * ); */ var JSON2 = require("LibsDir/json2"); var URL = "../AjaxHandler.aspx?r="; // 用來(lái)記錄每次請(qǐng)求的唯一標(biāo)識(shí), 鍵值對(duì)形式, 形如: // var requestIdentifier = { // SearchABSList: "b80a3876-9bca-40d1-b2cd-0daa799591e7", // SetABSUserColumns: "cafe3f01-2ee2-41f0-aeca-d630429f89f4", // }; var requestIdentifier = {}; // 唯一標(biāo)識(shí)生成方法 function generateGUID() { var d = new Date().getTime(); if (typeof performance !== "undefined" && typeof performance.now === "function") { d += performance.now(); } return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) { var r = (d + Math.random() * 16) % 16 | 0; d = Math.floor(d / 16); return (c === "x" ? r : (r & 0x3 | 0x8)).toString(16); }); } // 模塊主體 var ajaxRequest = ajaxRequest || {}; (function ($) { if (!$) { throw "jquery獲取失敗!"; } ajaxRequest.json = JSON2; /** * 觸發(fā)請(qǐng)求, 返回包裝成 Deferred 對(duì)象的 jqXHR * @param {object} userOptions 參數(shù)對(duì)象(包含方法名、參數(shù)對(duì)象、成功回調(diào)、失敗回調(diào)) * @param {string} serviceName 方法名 * @param {string} requestId 請(qǐng)求的唯一標(biāo)識(shí) * @returns object */ ajaxRequest.ajax = function (userOptions, serviceName, requestId) { userOptions = userOptions || {}; // 將參數(shù)對(duì)象與ajax的默認(rèn)項(xiàng)組成一個(gè)新的對(duì)象, 作為 jquery ajax 方法的配置項(xiàng) var options = $.extend({}, ajaxRequest.ajax.defaultOpts, userOptions); // 將 jquery ajax 方法默認(rèn)的 success 回調(diào)和 error 回調(diào)置為 undefined // .done()方法取代了的過(guò)時(shí)的jqXHR.success()方法 // .fail()方法取代了的過(guò)時(shí)的.error()方法 options.success = undefined; options.error = undefined; // 將 jqXHR 包裝成新的 Deferred 對(duì)象返回 // jQuery.Deferred([beforeStart]) 一個(gè)工廠函數(shù), 這個(gè)函數(shù)返回一個(gè)鏈?zhǔn)綄?shí)用對(duì)象 // beforeStart - 一個(gè)構(gòu)造函數(shù)返回之前調(diào)用的函數(shù) return $.Deferred(function ($dfd) { $.ajax(options) .done(function (result, textStatus, jqXHR) { if (requestId === requestIdentifier[serviceName]) { // 比對(duì)請(qǐng)求id, 保證返回結(jié)果的正確性 (重復(fù)請(qǐng)求有可能會(huì)帶來(lái)返回結(jié)果不可靠的問(wèn)題) ajaxRequest.ajax.handleResponse(result, $dfd, jqXHR, userOptions, serviceName, requestId); } }) .fail(function (jqXHR, textStatus, errorThrown) { if (requestId === requestIdentifier[serviceName]) { // jqXHR.status $dfd.reject.apply(this, arguments); userOptions.error.apply(this, arguments); } }); }); }; $.extend(ajaxRequest.ajax, { // $.ajax() 的默認(rèn)設(shè)置 defaultOpts: { // url: "../AjaxSecureHandler.aspx, dataType: "json", type: "POST", contentType: "application/x-www-form-urlencoded; charset=UTF-8" }, // 在業(yè)務(wù)代碼的回調(diào)執(zhí)行之前, 做一些統(tǒng)一處理, 實(shí)現(xiàn)代碼復(fù)用 // $dfd.resolve() 和 $dfd.reject() 的執(zhí)行, 會(huì)使得使用 .then()/.done() 中的回調(diào)方法得到執(zhí)行 // userOptions.success() 和 userOptions.error() 是調(diào)用用戶以參數(shù)形式傳入的成功回調(diào)函數(shù)和失敗回調(diào)函數(shù) // 一般來(lái)說(shuō), 上述兩種方式只會(huì)有一個(gè)真正起到作用, 這取決于用戶調(diào)用的方式: // 如果是使用 $.ajax().done().fail() 這種方式調(diào)用, 那么 $dfd.resolve()/$dfd.reject() 會(huì)起到作用 // 此時(shí) userOptions.success/userOptions.error 都是 undefined, 自然不會(huì)得到執(zhí)行, 反之亦然 handleResponse: function (result, $dfd, jqXHR, userOptions, serviceName, requestId) { if (!result) { $dfd && $dfd.reject(jqXHR, "error response format!"); userOptions.error(jqXHR, "error response format!"); return; } // 服務(wù)器已經(jīng)錯(cuò)誤 if (result.ErrorCode != "200") { $dfd && $dfd.reject(jqXHR, result.ErrorMessage); userOptions.error(jqXHR, result); return; } if (result.Data) { // 將大于2^53的數(shù)字(16位以上)包裹雙引號(hào), 避免溢出 var jsonStr = result.Data.replace(/(:s*)(d{16,})(s*,|s*})/g, "$1"$2"$3"); var resultData = ajaxRequest.json.parse(jsonStr); // $dfd.resolve() 執(zhí)行之后, 業(yè)務(wù)代碼中的回調(diào)會(huì)執(zhí)行, 即.then()/.done()方法會(huì)得到執(zhí)行 $dfd.resolve(resultData); // 如果是使用傳統(tǒng)的傳入成功回調(diào)函數(shù)的形式進(jìn)行調(diào)用的, 那么在此處調(diào)用用戶設(shè)定的成功回調(diào) userOptions.success && userOptions.success(resultData); } else { $dfd.resolve(); userOptions.success && userOptions.success(); } }, /** * 構(gòu)建請(qǐng)求參數(shù)對(duì)象 * @param {string} serviceName 方法名 * @param {object} input 傳入的參數(shù)對(duì)象 * @param {function} userSuccess 成功回調(diào) * @param {function} userError 失敗回調(diào) * @param {object} ajaxParams 其他參數(shù) * @returns object */ buildServiceRequest: function (serviceName, input, userSuccess, userError, ajaxParams) { // 這里是根據(jù)后臺(tái)要求構(gòu)建的 var requestData = { MethodAlias: serviceName, // 方法名 Parameter: input // 傳遞的參數(shù) }; var request = $.extend({}, ajaxParams, { // 這里要對(duì)傳遞的 JSON 字符串參數(shù)數(shù)據(jù)使用 escape 方法進(jìn)行編碼 // "data=" 是根據(jù)項(xiàng)目約定增加的,與 contentType 相對(duì)應(yīng) data: "data=" + escape(ajaxRequest.json.stringify(requestData)), success: userSuccess, error: function (jqXHR, textStatus, errorThrown) { // 這里是在請(qǐng)求出錯(cuò)的時(shí)候做一個(gè)統(tǒng)一處理, 輸出方法名和錯(cuò)誤對(duì)象 console.log(serviceName, jqXHR); if (userError && (typeof userError === "function")) { userError(jqXHR, textStatus, errorThrown); } } }); return request; }, // 構(gòu)建參數(shù)對(duì)象, 生成唯一標(biāo)識(shí), 觸發(fā)請(qǐng)求 triggerService: function (serviceName, input, success, error, ajaxParams) { // 構(gòu)建參數(shù)對(duì)象 var request = ajaxRequest.ajax.buildServiceRequest(serviceName, input, success, error, ajaxParams); // 生成此次 ajax 請(qǐng)求唯一標(biāo)識(shí) var requestId = requestIdentifier[serviceName] = generateGUID(); request.url = URL + requestId; // 觸發(fā)請(qǐng)求 return ajaxRequest.ajax(request, serviceName, requestId); } }); })(jQuery); module.exports = ajaxRequest;
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/103025.html
摘要:設(shè)置請(qǐng)求和接收響應(yīng)自己封裝簡(jiǎn)易這篇文章是承接前幾篇博客的是前幾篇繼續(xù)學(xué)習(xí)包括學(xué)習(xí)與理解和簡(jiǎn)化版自己實(shí)現(xiàn)等這篇文章只算是我的個(gè)人學(xué)習(xí)筆記內(nèi)容沒(méi)有精心排版一些錯(cuò)誤請(qǐng)見(jiàn)諒所有代碼都在這里從歷史可以看到所有代碼擺闊一個(gè)簡(jiǎn)易的服務(wù)器所有代碼在歷史里 Ajax設(shè)置請(qǐng)求和接收響應(yīng)、自己封裝簡(jiǎn)易jQuery.Ajax 這篇文章是承接前幾篇博客的,是前幾篇繼續(xù)學(xué)習(xí)包括Ajax學(xué)習(xí)與理解和簡(jiǎn)化版自己實(shí)現(xiàn)j...
摘要:和異步處理調(diào)用訪問(wèn)數(shù)據(jù)采用的方式,這是一個(gè)異步過(guò)程,異步過(guò)程最基本的處理方式是事件或回調(diào),其實(shí)這兩種處理方式實(shí)現(xiàn)原理差不多,都需要在調(diào)用異步過(guò)程的時(shí)候傳入一個(gè)在異步過(guò)程結(jié)束的時(shí)候調(diào)用的接口。 Ajax 和異步處理 調(diào)用 API 訪問(wèn)數(shù)據(jù)采用的 Ajax 方式,這是一個(gè)異步過(guò)程,異步過(guò)程最基本的處理方式是事件或回調(diào),其實(shí)這兩種處理方式實(shí)現(xiàn)原理差不多,都需要在調(diào)用異步過(guò)程的時(shí)候傳入一個(gè)在異...
摘要:為這些回調(diào)函數(shù)分別命名并分離存放可以在形式上減少嵌套,使代碼清晰,但仍然不能解決問(wèn)題。如果在一個(gè)結(jié)束成功或失敗,同前面的說(shuō)明后,添加針對(duì)成功或失敗的回調(diào),則回調(diào)函數(shù)會(huì)立即執(zhí)行。 異步? 我在很多地方都看到過(guò)異步(Asynchronous)這個(gè)詞,但在我還不是很理解這個(gè)概念的時(shí)候,卻發(fā)現(xiàn)自己常常會(huì)被當(dāng)做已經(jīng)很清楚(* ̄? ̄)。 如果你也有類似的情況,沒(méi)關(guān)系,搜索一下這個(gè)詞,就可以得到大致...
摘要:希望在做所有事情之前,操作文檔。不受層級(jí)限制子選擇器在給定的父元素下匹配所有子元素。相鄰選擇器匹配所有緊接在元素后的元素。判斷當(dāng)前對(duì)象中的某個(gè)元素是否包含指定類名,包含返回,不包含返回下標(biāo)過(guò)濾器精確選出指定下標(biāo)元素獲取第個(gè)元素。 原文鏈接 http://blog.poetries.top/2016... 首先,來(lái)了解一下jQuery學(xué)習(xí)的整體思路 showImg(https://seg...
摘要:在內(nèi)部還是調(diào)用這些方法。對(duì)象下標(biāo),從開始對(duì)象下標(biāo),從開始再次重申對(duì)象只能調(diào)用對(duì)象的,對(duì)象只能調(diào)用對(duì)象的對(duì)象轉(zhuǎn)成值得注意的是在腳本內(nèi),是代表對(duì)象的。對(duì)象轉(zhuǎn)成對(duì)象語(yǔ)法也非常簡(jiǎn)單在內(nèi)寫上對(duì)象,就變成了對(duì)象了。在文檔中對(duì)它的解釋是這樣子的。 什么是Jquery? Jquey就是一款跨主流瀏覽器的JavaScript庫(kù),簡(jiǎn)化JavaScript對(duì)HTML操作 就是封裝了JavaScript,能夠...
閱讀 3688·2021-11-16 11:41
閱讀 2895·2021-09-23 11:45
閱讀 698·2019-08-30 15:44
閱讀 551·2019-08-30 13:10
閱讀 1969·2019-08-30 12:49
閱讀 3537·2019-08-28 17:51
閱讀 1487·2019-08-26 12:20
閱讀 709·2019-08-23 17:56