jsonp的原理與實現(xiàn)

  1. 概述
    jsonp是一種跨域通信的手段佩捞,它的原理其實很簡單:

首先是利用script標(biāo)簽的src屬性來實現(xiàn)跨域。

通過將前端方法作為參數(shù)傳遞到服務(wù)器端闻葵,然后由服務(wù)器端注入?yún)?shù)之后再返回陪竿,實現(xiàn)服務(wù)器端向客戶端通信跷乐。

由于使用script標(biāo)簽的src屬性,因此只支持get方法

  1. 實現(xiàn)流程
    設(shè)定一個script標(biāo)簽

<script src="http://jsonp.js?callback=xxx"></script>
callback定義了一個函數(shù)名座硕,而遠(yuǎn)程服務(wù)端通過調(diào)用指定的函數(shù)并傳入?yún)?shù)來實現(xiàn)傳遞參數(shù)弛作,將fn(response)傳遞回客戶端

callback = !empty(_GET['callback']) ? _GET['callback'] : 'callback'; echocallback.'(.json_encode($data).)';
客戶端接收到返回的js腳本,開始解析和執(zhí)行fn(response)

  1. jsonp簡單實現(xiàn)
    一個簡單的jsonp實現(xiàn)华匾,其實就是拼接url映琳,然后將動態(tài)添加一個script元素到頭部。

function jsonp(req){
var script = document.createElement('script');
var url = req.url + '?callback=' + req.callback.name;
script.src = url;
document.getElementsByTagName('head')[0].appendChild(script);
}
前端js示例

function hello(res){
alert('hello ' + res.data);
}
jsonp({
url : '',
callback : hello
});
服務(wù)器端代碼

var http = require('http');
var urllib = require('url');

var port = 8080;
var data = {'data':'world'};

http.createServer(function(req,res){
var params = urllib.parse(req.url,true);
if(params.query.callback){
console.log(params.query.callback);
//jsonp
var str = params.query.callback + '(' + JSON.stringify(data) + ')';
res.end(str);
} else {
res.end();
}

}).listen(port,function(){
console.log('jsonp server is on');
});
然而蜘拉,這個實現(xiàn)雖然簡單萨西,但有一些不足的地方:

我們傳遞的回調(diào)必須是一個全局方法,我們都知道要盡量減少全局的方法旭旭。

需要加入一些參數(shù)校驗谎脯,確保接口可以正常執(zhí)行。

  1. 可靠的jsonp實現(xiàn)
    (function (global) {
    var id = 0,
    container = document.getElementsByTagName("head")[0];

    function jsonp(options) {
    if(!options || !options.url) return;

     var scriptNode = document.createElement("script"),
         data = options.data || {},
         url = options.url,
         callback = options.callback,
         fnName = "jsonp" + id++;
    
     // 添加回調(diào)函數(shù)
     data["callback"] = fnName;
    
     // 拼接url
     var params = [];
     for (var key in data) {
         params.push(encodeURIComponent(key) + "=" + encodeURIComponent(data[key]));
     }
     url = url.indexOf("?") > 0 ? (url + "&") : (url + "?");
     url += params.join("&");
     scriptNode.src = url;
    
     // 傳遞的是一個匿名的回調(diào)函數(shù)持寄,要執(zhí)行的話穿肄,暴露為一個全局方法
     global[fnName] = function (ret) {
         callback && callback(ret);
         container.removeChild(scriptNode);
         delete global[fnName];
     }
    
     // 出錯處理
     scriptNode.onerror = function () {
         callback && callback({error:"error"});
         container.removeChild(scriptNode);
         global[fnName] && delete global[fnName];
     }
    
     scriptNode.type = "text/javascript";
     container.appendChild(scriptNode)
    

    }

    global.jsonp = jsonp;

})(this);
使用示例

jsonp({
url : "www.exampe.com",
data : {id : 1},
callback : function (ret) {
console.log(ret);
}
});

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末年局,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子咸产,更是在濱河造成了極大的恐慌矢否,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件脑溢,死亡現(xiàn)場離奇詭異僵朗,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)屑彻,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進(jìn)店門验庙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人社牲,你說我怎么就攤上這事粪薛。” “怎么了搏恤?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵违寿,是天一觀的道長。 經(jīng)常有香客問我熟空,道長藤巢,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任息罗,我火速辦了婚禮掂咒,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘迈喉。我一直安慰自己绍刮,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布挨摸。 她就那樣靜靜地躺著录淡,像睡著了一般。 火紅的嫁衣襯著肌膚如雪油坝。 梳的紋絲不亂的頭發(fā)上嫉戚,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天,我揣著相機(jī)與錄音澈圈,去河邊找鬼彬檀。 笑死,一個胖子當(dāng)著我的面吹牛瞬女,可吹牛的內(nèi)容都是我干的窍帝。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼诽偷,長吁一口氣:“原來是場噩夢啊……” “哼坤学!你這毒婦竟也來了疯坤?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤深浮,失蹤者是張志新(化名)和其女友劉穎压怠,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體飞苇,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡菌瘫,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了布卡。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片雨让。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖忿等,靈堂內(nèi)的尸體忽然破棺而出栖忠,到底是詐尸還是另有隱情,我是刑警寧澤贸街,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布庵寞,位于F島的核電站,受9級特大地震影響匾浪,放射性物質(zhì)發(fā)生泄漏皇帮。R本人自食惡果不足惜卷哩,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一蛋辈、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧将谊,春花似錦冷溶、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至栋齿,卻和暖如春苗胀,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背瓦堵。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工基协, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人菇用。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓澜驮,卻偏偏與公主長得像,于是被迫代替她去往敵國和親惋鸥。 傳聞我的和親對象是個殘疾皇子杂穷,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內(nèi)容