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

資訊專欄INFORMATION COLUMN

原來(lái)你是這樣的jsonp(原理與具體實(shí)現(xiàn)細(xì)節(jié))

DangoSky / 4015人閱讀

摘要:但是有可能還不太它內(nèi)部具體是如何實(shí)現(xiàn)一個(gè)的,從請(qǐng)求的發(fā)出,到指定的成功或失敗回調(diào)函數(shù)的執(zhí)行。服務(wù)端會(huì)解析請(qǐng)求的至少拿到一個(gè)回調(diào)函數(shù)比如參數(shù)之后將數(shù)據(jù)放入其中返回給客戶端。

前言

原文地址

倉(cāng)庫(kù)地址

jsonp(JSON with padding)你一定不會(huì)陌生,前端向后端拿數(shù)據(jù)的方式之一,也是處理跨域請(qǐng)求的得利助手。

我們?cè)缫蚜?xí)慣,早已熟練了jQ或者zepto的ajax調(diào)用方式。但是有可能還不太它內(nèi)部具體是如何實(shí)現(xiàn)一個(gè)jsonp的,從請(qǐng)求的發(fā)出,到指定的成功(success)或失敗(error)回調(diào)函數(shù)的執(zhí)行。

這中間前端需要做什么?

后端又需要做些什么來(lái)支持?

超時(shí)場(chǎng)景又該如何處理?

整個(gè)生命周期會(huì)有多個(gè)鉤子可以被觸發(fā),而我們可以監(jiān)聽(tīng)哪些鉤子來(lái)得知請(qǐng)求的狀況?

讓我們從zepto.js的源碼出發(fā),一步步揭開(kāi)它的面紗。

(該篇文章重點(diǎn)是想說(shuō)jsonp實(shí)現(xiàn)過(guò)程,如果你想了解跨域相關(guān)的更多的知識(shí),可以谷歌,度娘一把)

絮叨一下jsonp的基本原理

jsonp是服務(wù)器與客戶端跨源通信的常用方法之一,具有簡(jiǎn)單易用,瀏覽器兼容性好等特點(diǎn)。

基本思想是啥呢

客戶端利用script標(biāo)簽可以跨域請(qǐng)求資源的性質(zhì),向網(wǎng)頁(yè)中動(dòng)態(tài)插入script標(biāo)簽,來(lái)向服務(wù)端請(qǐng)求數(shù)據(jù)。

服務(wù)端會(huì)解析請(qǐng)求的url,至少拿到一個(gè)回調(diào)函數(shù)(比如callback=myCallback)參數(shù),之后將數(shù)據(jù)放入其中返回給客戶端。

當(dāng)然jsonp不同于平常的ajax請(qǐng)求,它僅僅支持get類型的方式

如何使用

這里簡(jiǎn)單的介紹一下zepto.js是如果使用jsonp形式請(qǐng)求數(shù)據(jù)的,然后從使用的角度出發(fā)一步步分析源碼實(shí)現(xiàn)。

使用

$.ajax({
  url: "http://www.abc.com/api/xxx", // 請(qǐng)求的地址
  type: "get", // 當(dāng)然參數(shù)可以省略
  data: { // 傳給服務(wù)端的數(shù)據(jù),被加載url?的后面
    name: "qianlongo",
    sex: "boy"
  },
  dataType: "jsonp", // 預(yù)期服務(wù)器返回的數(shù)據(jù)類型
  jsonpCallback: "globalCallback", // 全局JSONP回調(diào)函數(shù)的 字符串(或返回的一個(gè)函數(shù))名
  timeout: 100, // 以毫秒為單位的請(qǐng)求超時(shí)時(shí)間, 0 表示不超時(shí)。
  success: function (data) { // 請(qǐng)求成功之后調(diào)用
    console.log("successCallback")
    console.log(data)
  },
  error: function (err) { // 請(qǐng)求出錯(cuò)時(shí)調(diào)用。 (超時(shí),解析錯(cuò)誤,或者狀態(tài)碼不在HTTP 2xx)
    console.log("errorCallback")
    console.log(err)
  },
  complete: function (data) { // 請(qǐng)求完成時(shí)調(diào)用,無(wú)論請(qǐng)求失敗或成功。
    console.log("compelete")
    console.log(data)
  }
})

function globalCallback (data) {
  console.log("globalCallback")
  console.log(data)
}   

在zepto中一個(gè)常見(jiàn)的jsonp請(qǐng)求配置就是這樣了,大家都很熟悉了。但是不知道大家有沒(méi)有發(fā)現(xiàn).

如果設(shè)置了timeout超時(shí)了,并且沒(méi)有設(shè)置jsonpCallback字段,那么控制臺(tái)幾乎都會(huì)出現(xiàn)一處報(bào)錯(cuò),如下圖

同樣還是發(fā)生在timeout,此時(shí)如果請(qǐng)求超時(shí)了,并且設(shè)置了jsonpCallback字段(注意這個(gè)時(shí)候是設(shè)置了),但是如果請(qǐng)求在超時(shí)之后完成了,你的jsonpCallback還是會(huì)被執(zhí)行。照理說(shuō)這個(gè)函數(shù)應(yīng)該是請(qǐng)求在超時(shí)時(shí)間內(nèi)完成才會(huì)被執(zhí)行啊!為毛這個(gè)時(shí)候超時(shí)了,還是會(huì)被執(zhí)行?。。?!

不急等我們一步步分析完就會(huì)知道這個(gè)答案了。

先看一下完整的代碼

因?yàn)閦epto中完成jsonp請(qǐng)求的處理基本都在$.ajaxJSONP完成,我們直接從該函數(shù)出發(fā)開(kāi)始分析。先整體看看這個(gè)函數(shù),有一個(gè)大概的印象,已經(jīng)加了大部分注釋?;蛘呖梢渣c(diǎn)擊這里查看

 $.ajaxJSONP = function (options, deferred) {
  // 直接調(diào)ajaxJSONP沒(méi)有傳入type,去走$.ajax
  if (!("type" in options)) return $.ajax(options)
  // 獲取callback函數(shù)名,此時(shí)未指定為undefined
  var _callbackName = options.jsonpCallback,
    // jsonpCallback可以是一個(gè)函數(shù)或者一個(gè)字符串
    // 是函數(shù)時(shí),執(zhí)行該函數(shù)拿到其返回值作為callback函數(shù)
    // 為字符串時(shí)直接賦值
    // 沒(méi)有傳入jsonpCallback,那么使用類似"Zepto3726472347"作為函數(shù)名
    callbackName = ($.isFunction(_callbackName) ?
      _callbackName() : _callbackName) || ("Zepto" + (jsonpID++)),
    // 創(chuàng)建一個(gè)script標(biāo)簽用來(lái)發(fā)送請(qǐng)求  
    script = document.createElement("script"),
    // 先讀取全局的callbackName函數(shù),因?yàn)楹竺鏁?huì)對(duì)該函數(shù)重寫,所以需要先保存一份
    originalCallback = window[callbackName],
    responseData,
    // 中止請(qǐng)求,觸發(fā)script元素上的error事件, 后面帶的參數(shù)是回調(diào)函數(shù)接收的參數(shù)
    abort = function (errorType) {
      $(script).triggerHandler("error", errorType || "abort")
    },
    xhr = { abort: abort }, abortTimeout

  if (deferred) deferred.promise(xhr)
  // 給script元素添加load和error事件
  $(script).on("load error", function (e, errorType) {
    // 清除超時(shí)定時(shí)器
    clearTimeout(abortTimeout)
    // 移除添加的元素(注意這里還off了,不然超時(shí)這種情況,請(qǐng)求回來(lái)了,還是會(huì)走回調(diào))
    $(script).off().remove()
    // 請(qǐng)求出錯(cuò)或后端沒(méi)有給callback中塞入數(shù)據(jù),將觸發(fā)error
    if (e.type == "error" || !responseData) {
      ajaxError(null, errorType || "error", xhr, options, deferred)
    } else {
      // 請(qǐng)求成功,調(diào)用成功回調(diào),請(qǐng)塞入數(shù)據(jù)responseData[0]
      ajaxSuccess(responseData[0], xhr, options, deferred)
    }
    // 將originalCallback重新賦值回去
    window[callbackName] = originalCallback
    // 并且判斷originalCallback是不是個(gè)函數(shù),如果是函數(shù),便執(zhí)行
    if (responseData && $.isFunction(originalCallback))
      originalCallback(responseData[0])
    // 清空閉包,釋放空間
    originalCallback = responseData = undefined
  })

  if (ajaxBeforeSend(xhr, options) === false) {
    abort("abort")
    return xhr
  }
  // 重寫全局上的callbackName
  window[callbackName] = function () {
    responseData = arguments
  }
  // 將回調(diào)函數(shù)名追加到?后面
  script.src = options.url.replace(/?(.+)=?/, "?$1=" + callbackName)
  // 添加script元素
  document.head.appendChild(script)
  // 超時(shí)處理函數(shù)
  if (options.timeout > 0) abortTimeout = setTimeout(function () {
    abort("timeout")
  }, options.timeout)

  return xhr
}

參數(shù)的基本處理

在執(zhí)行原理的第一步時(shí),zepto會(huì)先處理一下我們傳入的參數(shù)。

我們先來(lái)看看針對(duì)上面的例子我們發(fā)送請(qǐng)求的url最終會(huì)變成什么樣子,而參數(shù)處理正是為了得到這條url

傳了jsonpCallback時(shí)的url

http://www.abc.com/api/xxx?name=qianlongo&sex=boy&_=1497193375213&callback=globalCallback

沒(méi)有傳jsonpCallback時(shí)的url

http://www.abc.com/api/xxx?name=qianlongo&sex=boy&_=1497193562726&callback=Zepto1497193562723

相信你已經(jīng)看出來(lái)這兩條url有什么不同之處了。

_后面跟的時(shí)間戳不一樣

callback后面跟的回調(diào)函數(shù)名字不一樣

也就是說(shuō)如果你指定了成功的回調(diào)函數(shù)就用你的,沒(méi)指定他自己生成一個(gè)。

上參數(shù)處理代碼

var jsonpID = +new Date()

var _callbackName = options.jsonpCallback,
callbackName = ($.isFunction(_callbackName) ?
  _callbackName() : _callbackName) || ("Zepto" + (jsonpID++))

對(duì)于回調(diào)函數(shù)名的處理其實(shí)挺簡(jiǎn)單的,根據(jù)你是否在參數(shù)中傳了jsonpCallback,傳了是個(gè)函數(shù)就用函數(shù)的返回值,不是函數(shù)就直接用。
否則的話,就生成類似Zepto1497193562723的函數(shù)名。

繼續(xù)看
// 創(chuàng)建一個(gè)script標(biāo)簽用來(lái)發(fā)送請(qǐng)求 
script = document.createElement("script"),
// 先讀取全局的callbackName函數(shù),因?yàn)楹竺鏁?huì)對(duì)該函數(shù)重寫,所以需要先保存一份
originalCallback = window[callbackName],
// 請(qǐng)求完成后拿到的數(shù)據(jù)
responseData,
// 中止請(qǐng)求,觸發(fā)script元素上的error事件, 后面帶的參數(shù)是回調(diào)函數(shù)接收的參數(shù)
abort = function (errorType) {
  $(script).triggerHandler("error", errorType || "abort")
},
xhr = { abort: abort }, abortTimeout
// 對(duì).then或者.catch形式調(diào)用的支持,本文暫時(shí)不涉及這方面的解析
if (deferred) deferred.promise(xhr)

好啦,看到這里我們主要要關(guān)注的是

originalCallback = window[callbackName]

abort函數(shù)

對(duì)于1為什么要把全局的callbackName函數(shù)先保存一份呢?這里涉及到一個(gè)問(wèn)題。

請(qǐng)求回來(lái)的時(shí)候到底是不是直接執(zhí)行的你傳入的jsonpCallback函數(shù)?

解決這個(gè)問(wèn)題請(qǐng)看

// 重寫全局上的callbackName
window[callbackName] = function () {
  responseData = arguments
}

zepto中把全局的callbackName函數(shù)給重寫掉了,,導(dǎo)致后端返回?cái)?shù)據(jù)時(shí)執(zhí)行該函數(shù),就干了一件事,就是把數(shù)據(jù)賦值給了responseData這個(gè)變量。

那說(shuō)好的真正的callbackName函數(shù)呢? 如果我傳了jsonpCallback,我是會(huì)在里面做一些業(yè)務(wù)邏輯的啊,你都把我給重寫了,我的邏輯怎么辦?先留個(gè)疑問(wèn)在這里

對(duì)于關(guān)注點(diǎn)2abort函數(shù),這個(gè)函數(shù)的功能,就是手動(dòng)觸發(fā)添加在創(chuàng)建好的script元素身上的error事件的回調(diào)函數(shù)。后面的超時(shí)處理timeout以及請(qǐng)求出錯(cuò)都是利用的該函數(shù)。

超時(shí)處理

在看監(jiān)聽(tīng)script元素on error事件回調(diào)邏輯前,我們直接看最后一點(diǎn)東西

// 將回調(diào)函數(shù)名追加到?后面
script.src = options.url.replace(/?(.+)=?/, "?$1=" + callbackName)
// 添加script元素
document.head.appendChild(script)
// 超時(shí)處理函數(shù)
if (options.timeout > 0) abortTimeout = setTimeout(function () {
  abort("timeout")
}, options.timeout)

代理做了簡(jiǎn)單的注釋,這里除了將script元素插入網(wǎng)頁(yè)還定義了一個(gè)超時(shí)處理函數(shù),判斷條件是傳入的參數(shù)timeout是否大于0,所以當(dāng)你傳小于0或者負(fù)數(shù)啥的進(jìn)去,是不會(huì)當(dāng)做超時(shí)處理的。超時(shí)后其實(shí)就是觸發(fā)了script元素的error事件,并傳了參數(shù)timeout

真正的回調(diào)邏輯處理

接下來(lái)就是本文的重點(diǎn)了,zepto通過(guò)監(jiān)聽(tīng)script元素的load事件來(lái)監(jiān)聽(tīng)請(qǐng)求是否完成,以及給script添加了error事件,方便請(qǐng)求出錯(cuò)和超時(shí)處理。而用戶需要的成功和失敗的處理也是在這里面完成

clearTimeout(abortTimeout)
$(script).off().remove()
if (e.type == "error" || !responseData) {
  ajaxError(null, errorType || "error", xhr, options, deferred)
} else {
  ajaxSuccess(responseData[0], xhr, options, deferred)
}
window[callbackName] = originalCallback
if (responseData && $.isFunction(originalCallback))
  originalCallback(responseData[0])
originalCallback = responseData = undefined

script元素真正的事件處理程序代碼也不多,開(kāi)頭有這兩句話

// 清楚超時(shí)定時(shí)器
clearTimeout(abortTimeout)
// 從網(wǎng)頁(yè)中移除創(chuàng)建的script元素以及將掛在它上面的所有事件都移除
$(script).off().remove()

起什么作用呢?

第一句自然是針對(duì)超時(shí)處理,如果請(qǐng)求在指定超時(shí)時(shí)間之前完成,自然是要把他清除一下,不然指定的時(shí)間到了,超時(shí)的回調(diào)還是會(huì)執(zhí)行,這是不對(duì)的。

第二句話,把創(chuàng)建的script元素從網(wǎng)頁(yè)中給刪除掉,綁定的事件("load error")也全部移除,干嘛要把事件都給移除呢?你想想,一個(gè)請(qǐng)求已經(jīng)發(fā)出去了,我們還能讓他半途停止嗎?該是不能吧,但是我們能夠阻止請(qǐng)求回來(lái)之后要做的事情呀!而這個(gè)回調(diào)不就是請(qǐng)求回來(lái)之后要做的事情么。

請(qǐng)求成功或失敗的處理

if (e.type == "error" || !responseData) {
  ajaxError(null, errorType || "error", xhr, options, deferred)
} else {
  ajaxSuccess(responseData[0], xhr, options, deferred)
}

那么再接下來(lái),就是請(qǐng)求的成功或失敗的處理了。失敗的條件就是觸發(fā)了error事件(不管是超時(shí)還是解析錯(cuò)誤,又或者狀態(tài)碼不在HTTP 2xx),甚至如果后端沒(méi)有正確給到數(shù)據(jù)responseData也是錯(cuò)誤。

再回顧一下responseData是怎么來(lái)的

// 重寫全局上的callbackName
window[callbackName] = function () {
  responseData = arguments
}

ajaxErro函數(shù)究竟做了些啥事呢?

ajaxError

// type: "timeout", "error", "abort", "parsererror"
function ajaxError(error, type, xhr, settings, deferred) {
  var context = settings.context
  // 執(zhí)行用戶傳進(jìn)去的error函數(shù),注意這里的context決定了error函數(shù)中的this執(zhí)行
  settings.error.call(context, xhr, type, error)
  if (deferred) deferred.rejectWith(context, [xhr, type, error])
  // 觸發(fā)全局的鉤子ajaxError
  triggerGlobal(settings, context, "ajaxError", [xhr, settings, error || type])
  // 調(diào)用ajaxComplete函數(shù)
  ajaxComplete(type, xhr, settings)
}

可以看到他調(diào)用了我們穿進(jìn)去的error函數(shù),并且觸發(fā)了全局的ajaxError鉤子,所以我們其實(shí)可以在document上監(jiān)聽(tīng)一個(gè)鉤子

$(document).on("ajaxError", function (e) {
  console.log("ajaxError")
  console.log(e)
})

這個(gè)時(shí)候便可以拿到請(qǐng)求出錯(cuò)的信息了

ajaxComplete

// status: "success", "notmodified", "error", "timeout", "abort", "parsererror"
function ajaxComplete(status, xhr, settings) {
  var context = settings.context
  // 調(diào)用傳進(jìn)來(lái)的complete函數(shù)
  settings.complete.call(context, xhr, status)
  // 觸發(fā)全局的ajaxComplete鉤子
  triggerGlobal(settings, context, "ajaxComplete", [xhr, settings])
  // 請(qǐng)求結(jié)束
  ajaxStop(settings)
}

ajaxStop

function ajaxStop(settings) {
  if (settings.global && !(--$.active)) triggerGlobal(settings, null, "ajaxStop")
}

同理我們可以監(jiān)聽(tīng)ajaxCompleteajaxStop鉤子

$(document).on("ajaxComplete ajaxStop", function (e) {
  console.log("ajaxComplete")
  console.log(e)
})

處理完失敗的情況那么接下來(lái)就是成功的處理了,主要調(diào)用了ajaxSuccess函數(shù)

ajaxSuccess

function ajaxSuccess(data, xhr, settings, deferred) {
  var context = settings.context, status = "success"
  // 調(diào)用傳進(jìn)來(lái)的成功的回調(diào)函數(shù)
  settings.success.call(context, data, status, xhr)
  if (deferred) deferred.resolveWith(context, [data, status, xhr])
  // 觸發(fā)全局的ajaxSuccess
  triggerGlobal(settings, context, "ajaxSuccess", [xhr, settings, data])
  // 執(zhí)行請(qǐng)求完成的回調(diào),成功和失敗都執(zhí)行了該回調(diào)
  ajaxComplete(status, xhr, settings)
}

原來(lái)我們平時(shí)傳入的success函數(shù)是在這里被執(zhí)行的。但是有一個(gè)疑問(wèn)啊!,我們知道我們是可以不傳入success函數(shù)的,當(dāng)我們指定jsonpCallback的時(shí),請(qǐng)求成功同樣會(huì)走jsonpCallback函數(shù),但是好像ajaxSuccess沒(méi)有執(zhí)行這個(gè)函數(shù),具體在處理的呢?

繼續(xù)往下看

// 重寫全局上的callbackName
window[callbackName] = function () {
  responseData = arguments
}


// 將originalCallback重新賦值回去
window[callbackName] = originalCallback
// 并且判斷originalCallback是不是個(gè)函數(shù),如果是函數(shù),便執(zhí)行
if (responseData && $.isFunction(originalCallback))
  originalCallback(responseData[0])

為了徹底搞清楚zepto把我們指定的回調(diào)函數(shù)重寫的原因,我再次加了重寫的代碼在這里??梢钥闯觯貙懙哪康?,就是為了拿到后端返回的數(shù)據(jù),而拿到數(shù)據(jù)之后便方便我們?cè)谄渌胤届`活的處理了,當(dāng)然指定的回調(diào)函數(shù)還是要重新賦值回去(這也是開(kāi)頭要保留一份該函數(shù)的本質(zhì)原因),如果是個(gè)函數(shù),就將數(shù)據(jù),塞進(jìn)去執(zhí)行。

分析到這里我相信你已經(jīng)幾乎明白了jsonp實(shí)現(xiàn)的基本原理,文章頂部說(shuō)的幾個(gè)問(wèn)題,我們也在這個(gè)過(guò)程中解答了。

這中間前端需要做什么?

后端又需要做些什么來(lái)支持?(接下來(lái)以例子說(shuō)明)

超時(shí)場(chǎng)景又該如何處理?

整個(gè)生命周期會(huì)有多個(gè)鉤子可以被觸發(fā),而我們可以監(jiān)聽(tīng)哪些鉤子來(lái)得知請(qǐng)求的狀況?

砰砰砰?。?!,親們還記得開(kāi)頭的時(shí)候留了這兩個(gè)問(wèn)題嗎?

在zepto中一個(gè)常見(jiàn)的jsonp請(qǐng)求配置就是這樣了,大家都很熟悉了。但是不知道大家有沒(méi)有發(fā)現(xiàn).

如果設(shè)置了timeout超時(shí)了,并且沒(méi)有設(shè)置jsonpCallback字段,那么控制臺(tái)幾乎都會(huì)出現(xiàn)一處報(bào)錯(cuò),如下圖

同樣還是發(fā)生在timeout,此時(shí)如果請(qǐng)求超時(shí)了,并且設(shè)置了jsonpCallback字段(注意這個(gè)時(shí)候是設(shè)置了),但是如果請(qǐng)求在超時(shí)之后完成了,你的jsonpCallback還是會(huì)被執(zhí)行。照理說(shuō)這個(gè)函數(shù)應(yīng)該是請(qǐng)求在超時(shí)時(shí)間內(nèi)完成才會(huì)被執(zhí)行?。槊@個(gè)時(shí)候超時(shí)了,還是會(huì)被執(zhí)行啊?。?!

問(wèn)題1:為什么會(huì)報(bào)錯(cuò)呢?

對(duì)于沒(méi)有指定jsonpCallback

此時(shí)我們給后端的回調(diào)函數(shù)名是類似Zepto1497193562723

window[callbackName] = originalCallback

超時(shí)的時(shí)候同樣會(huì)走load error的回調(diào),當(dāng)這句話執(zhí)行的時(shí)候,Zepto1497193562723被設(shè)置成了undefined,當(dāng)然后端返回?cái)?shù)據(jù)的時(shí)候去執(zhí)行

Zepto1497193562723({xxx: "yyy"})

自然就報(bào)錯(cuò)了。

問(wèn)題2呢? 其實(shí)同樣還是上面那句話,只不過(guò)此時(shí)我們指定了jsonpCallback,超時(shí)的時(shí)候雖然取消了script元素的的load error事件,意味著在超時(shí)之后請(qǐng)求即便回來(lái)了,也不會(huì)走到對(duì)應(yīng)的回調(diào)函數(shù)中去。但是別忘記,超時(shí)我們手動(dòng)觸發(fā)了script元素的error事件

$(script).triggerHandler("error", errorType || "abort")

原本被重寫的callback函數(shù)也會(huì)被重新賦值回去,此刻,即便script元素的load error回調(diào)不會(huì)被執(zhí)行,但我們指定的jsonpCallback還是會(huì)被執(zhí)行的。這也就解了問(wèn)題2.

用koa做服務(wù)端,zepto發(fā)jsonp請(qǐng)求

最后我們?cè)儆胟oa,模擬服務(wù)端的api,用zepto來(lái)請(qǐng)求他。

如果你對(duì)源碼感興趣可以點(diǎn)擊這里查看koa-todo-list

找到根目錄的testJsonp.js文件即是服務(wù)端主要代碼

前端代碼

html


js

$("button").on("click", () => {
  $.ajax({
    type: "get",
    url: "/showData",
    data: {
      name: "qianlongo",
      sex: "boy"
    },
    dataType: "jsonp",
    success: function (res) {
      console.log("success")
      console.log(res)
      $("
").text(JSON.stringify(res)).appendTo("body")
    },
    error: function (res) {
      console.log("error")
      console.log(res)
    }
  })
})

服務(wù)端主要代碼

var koa = require("koa");
var route = require("koa-route");
var path = require("path");
var parse = require("co-body");
var render = require("./app/lib/render.js");
var app = koa();

app.use(route.get("/showJsonpPage", showJsonpPage))
app.use(route.get("/showData", showData))

function * showJsonpPage () {
  var sHtml = yield render("jsonp")
  this.body = sHtml
}

function * showData (next) {
  let {callback, name, sex, randomNum} = this.query
  
  this.type = "text/javascript"
  let callbackData = {
    status: 0,
    message: "ok",
    data: {
      name,
      sex,
      randomNum
    }
  }

  this.body = `${callback}(${JSON.stringify(callbackData)})`
  console.log(this.query)
}

app.listen(3000);
console.log("listening port 3000");

運(yùn)行截圖

結(jié)尾

希望把jsonp的實(shí)現(xiàn)原理說(shuō)清楚了,歡迎大家拍磚。

如果對(duì)你有一點(diǎn)點(diǎn)幫助,點(diǎn)擊這里,加一個(gè)小星星好不好呀

如果對(duì)你有一點(diǎn)點(diǎn)幫助,點(diǎn)擊這里,加一個(gè)小星星好不好呀

如果對(duì)你有一點(diǎn)點(diǎn)幫助,點(diǎn)擊這里,加一個(gè)小星星好不好呀

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

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

相關(guān)文章

  • JSONP原理

    摘要:高級(jí)部分前后端聯(lián)動(dòng)瀏覽器服務(wù)器數(shù)據(jù)庫(kù)是什么文件系統(tǒng)是一種數(shù)據(jù)庫(kù)是一種數(shù)據(jù)庫(kù)也是一個(gè)軟件只要能長(zhǎng)久地存數(shù)據(jù),就是數(shù)據(jù)庫(kù)前后端如何配合接下來(lái)我們用一個(gè)文件充當(dāng)數(shù)據(jù)庫(kù)實(shí)際上數(shù)據(jù)庫(kù)的存儲(chǔ)內(nèi)容本質(zhì)就是一個(gè)帶有結(jié)構(gòu)的文件捋一捋前后端交互的過(guò)程代碼在這里 jsonp javascript高級(jí)部分:前后端聯(lián)動(dòng),瀏覽器+服務(wù)器 1數(shù)據(jù)庫(kù)是什么 文件系統(tǒng)是一種數(shù)據(jù)庫(kù)MySQL 是一種數(shù)據(jù)庫(kù),也是一個(gè)軟件只...

    testHs 評(píng)論0 收藏0
  • zepto源碼分析之form模塊

    摘要:形如源代碼在的原型上添加了相關(guān)方法。類似源代碼每個(gè)表單的和都通過(guò)編碼最后通過(guò)符號(hào)分割有了的基礎(chǔ),就是將相應(yīng)的和都通過(guò)編碼,然后用符號(hào)進(jìn)行分割,也就達(dá)到了我們要的結(jié)果。 前言 JavaScript最初的一個(gè)應(yīng)用場(chǎng)景就是分擔(dān)服務(wù)器處理表單的責(zé)任,打破處處依賴服務(wù)器的局面,這篇文章主要介紹zepto中form模塊關(guān)于表單處理的幾個(gè)方法,serialize、serializeArray、sub...

    Muninn 評(píng)論0 收藏0
  • JSONP原理剖析

    摘要:運(yùn)行一下頁(yè)面,成功彈出提示窗口,的執(zhí)行全過(guò)程順利完成到這里為止的話,相信你已經(jīng)能夠理解的客戶端實(shí)現(xiàn)原理了吧剩下的就是如何把代碼封裝一下,以便于與用戶界面交互,從而實(shí)現(xiàn)多次和重復(fù)調(diào)用。 先說(shuō)說(shuō)JSONP是怎么產(chǎn)生的: 其實(shí)網(wǎng)上關(guān)于JSONP的講解有很多,但卻千篇一律,而且云里霧里,對(duì)于很多剛接觸的人來(lái)講理解起來(lái)有些困難,小可不才,試著用自己的方式來(lái)闡釋一下這個(gè)問(wèn)題,看看是否有幫助。 1、...

    DangoSky 評(píng)論0 收藏0
  • 這些Zepto中實(shí)用方法集

    摘要:對(duì)象字面量形式通過(guò)構(gòu)造函數(shù)創(chuàng)建中是如何判斷的呢判斷是否為純粹的對(duì)象,必須滿足首先必須是對(duì)象不是對(duì)象并且原型要和的原型相等方法返回指定對(duì)象的原型即內(nèi)部屬性的值如果沒(méi)有繼承屬性,則返回。 前言 時(shí)間過(guò)得可真快,轉(zhuǎn)眼間2017年已去大半有余,你就說(shuō)嚇不嚇人,這一年你成長(zhǎng)了多少,是否荒度了很多時(shí)光,亦或者天天向上,收獲滿滿。今天主要寫一些看Zepto基礎(chǔ)模塊時(shí),比較實(shí)用的部分內(nèi)部方法,在我們?nèi)?..

    caozhijian 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<