成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

一篇文章吃透Jsonp

seal_de / 919人閱讀

摘要:前言最近因?yàn)楣ぷ鞯木壒?,幾乎把市面上所有庫都下載了一遍,卻發(fā)現(xiàn)沒有百分百讓我滿意的,最后自己手動改寫了,才符合了要求,也因此有了這篇文章。在這一點(diǎn)上不得不說做的很好,的函數(shù)包含了對各種情況的處理,還偽造了一個狀態(tài)碼的返回。

前言

最近因?yàn)楣ぷ鞯木壒?,幾乎把市面上所有Jsonp庫都下載了一遍,卻發(fā)現(xiàn)沒有百分百讓我滿意的,最后自己手動改寫了Jsonp,才符合了要求,也因此有了這篇文章。本文示例詳實(shí),代碼簡單,想弄明白Jsonp, 這一篇文章就夠了。

什么是Jsonp

因?yàn)锳JAX收到瀏覽器同源策略的限制,導(dǎo)致在跨域上有心無力,經(jīng)常需要后臺同學(xué)的幫助。而在瀏覽器中,所有帶有src的標(biāo)簽都是不受同源策略限制的,如image, script。Jsonp上就是利用了script標(biāo)簽的這個特點(diǎn),來實(shí)現(xiàn)跨域的。

其中,Jsonp和AJAX的原理完全不同,只不過Jquery帶了個很不好的頭,把兩個東西封裝在一起了,所以經(jīng)常讓新的同學(xué)混淆了。

Jsonp的原理:script src
AJAX的原理:xhr

舉一個最簡單的Jsonp的例子:





    
    
    
    Jsonp簡單示例






http://www.qq.com/getJsonp?callback=jsonCallback這個鏈接返回的內(nèi)容應(yīng)該是

jsonpCallback({
    msg: success
})

這樣,相當(dāng)于后臺調(diào)用了前臺提前寫好的callback函數(shù),將要返回的數(shù)據(jù)當(dāng)做callback函數(shù)的參數(shù)傳入,這樣前端就拿到后臺傳回來的數(shù)據(jù)了。

改寫Jsonp

但是坦白來說,單純的拿到數(shù)據(jù)并不能讓我們滿意。一個合適的請求函數(shù),必然包含對成功、失敗、超時的處理,就像我們上面寫的那個簡單示例,一旦出現(xiàn)異常,就不能讓我們滿意了。

在這一點(diǎn)上不得不說Jquery做的很好,Jquery的Jsonp函數(shù)包含了對各種情況的處理,還偽造了一個http狀態(tài)碼的返回。

Jsonp和AJAX不同,是拿不到狀態(tài)碼的,但是Jquery對于所有的錯誤都賦予了一個404的狀態(tài)碼,也是機(jī)智

對比其他的組件庫(axios-jsonp, axios-jsonp-pro, jsonp, fetch=jsonp-es6), 要不就是完全沒有對超時的處理,要不然就是把錯誤和超時混成一譚,更有甚者,有些都不能自定義callback函數(shù)的名字。這簡直太過分了。

那我為什么不選擇Jquery呢?因?yàn)樘罅耍瑆ebpack引入JQuery后瞬間大了80K, 而且多帶帶將Jsonp打包出來也有70K的樣子,而我的源碼只有20K,這是我不能接受的。

jsonp這個組件的問題是沒有對錯誤的處理,理解了Jsonp的原理,我們能很容易的添加上這塊的邏輯,以下是添加后的源碼:

/**
 * Module exports.
 */

module.exports = jsonp;

/**
 * Callback index.
 */

var count = 0;

/**
 * Noop function.
 */

function noop(){}

/**
 * JSONP handler
 *
 * Options:
 *  - param {String} qs parameter (`callback`)
 *  - prefix {String} qs parameter (`__jp`)
 *  - name {String} qs parameter (`prefix` + incr)
 *  - timeout {Number} how long after a timeout error is emitted (`60000`)
 *
 * @param {String} url
 * @param {Object|Function} optional options / callback
 * @param {Function} optional callback
 */

function jsonp(url, opts, fn){
  if ("function" == typeof opts) {
    fn = opts;
    opts = {};
  }
  if (!opts) opts = {};

  var prefix = opts.prefix || "__jp";

  // use the callback name that was passed if one was provided.
  // otherwise generate a unique name by incrementing our counter.
  var id = opts.name || (prefix + (count++));

  var param = opts.param || "callback";
  var timeout = null != opts.timeout ? opts.timeout : 60000;
  var enc = encodeURIComponent;
  var target = document.getElementsByTagName("script")[0] || document.head;
  var script;
  var timer;


  if (timeout) {
    timer = setTimeout(function(){
      cleanup();
      if (fn) fn(new Error("Timeout"));
    }, timeout);
  }

  function cleanup(){
    if (script.parentNode) script.parentNode.removeChild(script);
    window[id] = noop;
    if (timer) clearTimeout(timer);
  }

  function cancel(){
    if (window[id]) {
      cleanup();
    }
  }

  window[id] = function(data){
    cleanup();
    if (fn) fn(null, data);
  };

  // add qs component
  url += (~url.indexOf("?") ? "&" : "?") + param + "=" + enc(id);
  url = url.replace("?&", "?");

  // create script
  script = document.createElement("script");
  script.src = url;
  
  // 添加對錯誤的處理
  script.onerror = function (evt) {
      if (fn) fn(new Error("Error"));
      if (timer) clearTimeout(timer)
  }
  target.parentNode.insertBefore(script, target);

  return cancel;
}

因?yàn)榇蟛糠质侨思业拇a,我也就不班門弄斧了,有需要的可以直接npm install jsonp, 然后比對node_modules/jsonp/index.js進(jìn)行修改;有需要對Jsonp有更詳細(xì)的處理的,也可以在我的基礎(chǔ)上繼續(xù)添加。

總結(jié)

Jsonp的本質(zhì)就是創(chuàng)建一個回調(diào)函數(shù),然后在遠(yuǎn)程服務(wù)上調(diào)用這個函數(shù)并且將JSON數(shù)據(jù)形式作為參數(shù)傳遞,完成回調(diào)。比起另外兩種后臺無感知的跨域方案:image src、fetch no-cor,Jsonp可以對錯誤和超時進(jìn)行處理,也能對后臺返回的數(shù)據(jù)進(jìn)行分析;而對于AJAX,Jsonp免去了后臺添加跨域頭的煩惱,后臺的改動較小,一次寫好,終生受用(跨域頭還要不斷維護(hù)白名單)。這三種方案都有各自的使用場景,要在不同的場景進(jìn)行恰當(dāng)?shù)倪x用,以上。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/92627.html

相關(guān)文章

  • 前端20個真正靈魂拷問,吃透這些你就是中級前端工程師 【上篇】

    摘要:還是老規(guī)矩,從易到難吧傳統(tǒng)的定時器,異步編程等。分配對象時,先是在空間中進(jìn)行分配。內(nèi)存泄漏內(nèi)存泄漏是指程序中己動態(tài)分配的堆內(nèi)存由于某種原因程序未釋放或無法釋放,造成系統(tǒng)內(nèi)存的浪費(fèi),導(dǎo)致程序運(yùn)行速度減慢甚至系統(tǒng)崩潰等嚴(yán)重后果。 showImg(https://segmentfault.com/img/bVbwkad?w=1286&h=876); 網(wǎng)上參差不棄的面試題,本文由淺入深,讓你在...

    mdluo 評論0 收藏0
  • 前端20個真正靈魂拷問,吃透這些你就是中級前端工程師 【上篇】

    摘要:還是老規(guī)矩,從易到難吧傳統(tǒng)的定時器,異步編程等。分配對象時,先是在空間中進(jìn)行分配。內(nèi)存泄漏內(nèi)存泄漏是指程序中己動態(tài)分配的堆內(nèi)存由于某種原因程序未釋放或無法釋放,造成系統(tǒng)內(nèi)存的浪費(fèi),導(dǎo)致程序運(yùn)行速度減慢甚至系統(tǒng)崩潰等嚴(yán)重后果。 showImg(https://segmentfault.com/img/bVbwkad?w=1286&h=876); 網(wǎng)上參差不棄的面試題,本文由淺入深,讓你在...

    leap_frog 評論0 收藏0
  • 5分鐘吃透React Native Flexbox

    摘要:在中是主流布局方式。它有三種狀態(tài)正數(shù)零與負(fù)數(shù)。來看下運(yùn)行效果。這是為正數(shù)的情況,如果,控件的大小就會根據(jù)設(shè)置的與來固定顯示。如果發(fā)現(xiàn)生效的方式請務(wù)必告知。在中有主軸與副軸之分,主軸控制的排列方向,默認(rèn)為。默認(rèn)值為,繼承父容器的屬性。 今天我們來聊聊Flexbox,它是前端的一個布局方式。在React Native中是主流布局方式。如果你剛剛?cè)腴TReact Native,或者沒有多少前端...

    developerworks 評論0 收藏0
  • 5分鐘吃透React Native Flexbox

    摘要:在中是主流布局方式。它有三種狀態(tài)正數(shù)零與負(fù)數(shù)。來看下運(yùn)行效果。這是為正數(shù)的情況,如果,控件的大小就會根據(jù)設(shè)置的與來固定顯示。如果發(fā)現(xiàn)生效的方式請務(wù)必告知。在中有主軸與副軸之分,主軸控制的排列方向,默認(rèn)為。默認(rèn)值為,繼承父容器的屬性。 今天我們來聊聊Flexbox,它是前端的一個布局方式。在React Native中是主流布局方式。如果你剛剛?cè)腴TReact Native,或者沒有多少前端...

    Nekron 評論0 收藏0
  • 吃透動態(tài)代理,解密spring AOP源碼(四)

    摘要:值得一提的是由于采用動態(tài)創(chuàng)建子類的方式生成代理對象,所以不能對目標(biāo)類中的方法進(jìn)行代理。動態(tài)代理中生成的代理類是子類,調(diào)試的時候可以看到,打開源碼可看到實(shí)現(xiàn)了和也就實(shí)現(xiàn)方法。 前面講到了動態(tài)代理的底層原理,接下來我們來看一下aop的動態(tài)代理.Spring AOP使用了兩種代理機(jī)制:一種是基于JDK的動態(tài)代理,一種是基于CGLib的動態(tài)代理. ①JDK動態(tài)代理:使用JDK創(chuàng)建代理有一個限制...

    Codeing_ls 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<