面試必問之JSONP

我的筆記,暫時沒有附帶源代碼,見諒。
第一部分闡述什麼是JSONP,附帶面試題一個。
第二部分是發展歷程,img法,script法,JSONP法。沒有源代碼閱讀會筆記困難,再次見諒。
第三部分隨筆記錄一些基礎知識。javascript


JSONP

請求方:frank.com 的前端程序員(瀏覽器)
響應方:jack.com 的後端程序員(服務器)html

  1. 請求方建立 script,src 指向響應方,同時傳一個查詢參數 ?callbackName=yyy
  2. 響應方根據查詢參數callbackName,構造形如
    i.yyy.call(undefined, '你要的數據')
    ii.yyy('你要的數據')
       這樣的響應
  3. 瀏覽器接收到響應,就會執行 yyy.call(undefined, '你要的數據')
  4. 那麼請求方就知道了他要的數據

這就是 JSONP
約定:前端

  1. callbackName -> callback
  2. yyy -> 隨機數 好比xxx123145123()

面試題:

請問JSONP爲何不能發POST請求?
第一句話: 由於JSONP是經過動態建立script實現的。
第二句話: 動態建立script的時候只能用GET,不能用POSTjava


  • img更新法:用img悄無聲息地建立一個請求。只能get,不能post。 若是狀態碼是2XX就是請求成功,3xx是重定向,4xx就是客戶端錯誤,5xx是服務器錯誤。
button.addEventLister('click', (e)=>{
    let image = document.creatElement('img')
    img.src = '/pay'
    image.onload = function(){ // 狀態碼是 200~299 則表示成功
        alert('打錢成功')
        amount.innerText = amount.innerText - 1
    }
    image.onerror = function(){ // 狀態碼大於等於 400 則表示失敗
        alert('打錢失敗')
    }
})
複製代碼
  • script請求法(SRJ):比img請求法更快;瀏覽器會執行script的內容即瀏覽器返回的內容,因此就不須要onload、onerror了;
    SRJ: server rendered JavaScript 服務器返回的js,這是AJAX出來前的無刷新局部更新頁面內容的方案。
           特色:script可使用另外一個網站的JS。
<script>
button.addEventLister('click', (e)=>{
    let script = document.creatElement('script')
    script.src = '/apy'
    // 只這樣作是不行的。必須把下句代碼放在body裏才能夠,不能放在js文件
    // 只有把下句代碼放在頁面裏,瀏覽器纔會發請求
    document.body.appenChild(script)
    script.onerror = function(){
        alert('打錢失敗')
    }
})
</script>

index.js:
response.write(`amount.innerText = amount.innerText - 1`)
複製代碼

可是每次打錢成功都會建立一個script,html就變的很醜,因此咱們要打錢成功或失敗後刪除這個動態建立的script:node

//只需監聽script的onload和onerror,都刪除這個script便可
script.onload = function(){
    e.currentTarget.remove()
    }
script.onerror = function(){
    alert('打錢失敗')
    e.currentTarget.remove()
}
複製代碼

script請求法過程描述:jquery

若用戶點擊了打錢的按鈕,就建立一個script,script的src就是要請求的路徑,而後把script放到頁面裏,這樣瀏
覽器就會去發起這個路徑的get請求;若是get成功了,它首先會執行服務器返回的js的響應,這個響應就是操做頁面局
部的刷新,爲何會把響應當成script執行呢?一是由於咱們設置的response.setHeader就是application/java
script;二是我前端確實把它放在script標籤裏的。執行以後,用戶就看到金額減小了,減小以後咱們就去監聽,
不管成功失敗,都會刪除這個script。
複製代碼

可是

若是A網站的程序員要去調用B網站的JS,就必須對B網站的頁面細節知道的很清楚,不然接口就對不上,這樣耦合太大了!因此咱們要解除耦合!程序員

方法:我調用個函數就好了,我不關內心面是什麼面試

response.write(`amount.innerText = amount.innerText - 1`) 
改爲
response.write(`xxx.call(undefined,'打錢成功'`) 
同時在A網站JS裏,監聽xxx函數。
複製代碼

這個函數名xxx雙方是怎麼傳遞的呢?ajax

A:script.src='http://B.com/pay?callback=xxx'
B:response.write(`$(query.callback).call(undefined,'打錢成功'`) 
複製代碼

代碼細節1: json

JSONP

請求方:frank.com 的前端程序員(瀏覽器)
響應方:jack.com 的後端程序員(服務器)

  1. 請求方建立 script,src 指向響應方,同時傳一個查詢參數 ?callbackName=yyy
  2. 響應方根據查詢參數callbackName,構造形如
    i.yyy.call(undefined, '你要的數據')
    ii.yyy('你要的數據')
       這樣的響應
  3. 瀏覽器接收到響應,就會執行 yyy.call(undefined, '你要的數據')
  4. 那麼請求方就知道了他要的數據

這就是 JSONP
約定:

  1. callbackName -> callback
  2. yyy -> 隨機數 好比xxx123145123()
functionName = 'om'+parseInt(Math.random()*100000,10)
window[functionName] = function(result){...}
script.src = 'http://jack.com:8002/pay?callback=' + functionName
複製代碼

JSONP

button.addEventListener('click', (e)=>{
    let script = document.createElement('script')
    let functionName = 'frank'+ parseInt(Math.random()*10000000 ,10)
    window[functionName] = function(){  // 每次請求以前搞出一個隨機的函數
        amount.innerText = amount.innerText - 0 - 1
    }
    script.src = '/pay?callback=' + functionName
    document.body.appendChild(script)
    script.onload = function(e){ // 狀態碼是 200~299 則表示成功
        e.currentTarget.remove()
        delete window[functionName] // 請求完了就幹掉這個隨機函數
    }
    script.onerror = function(e){ // 狀態碼大於等於 400 則表示失敗
        e.currentTarget.remove()
        delete window[functionName] // 請求完了就幹掉這個隨機函數
    }
})
複製代碼
//後端代碼
...
if (path === '/pay'){
    let amount = fs.readFileSync('./db', 'utf8')
    amount -= 1
    fs.writeFileSync('./db', amount)
    let callbackName = query.callback
    response.setHeader('Content-Type', 'application/javascript')
    response.write(`
        ${callbackName}.call(undefined, 'success')
    `)
    response.end()
}
複製代碼

寫了這麼多,jQuery已經幫咱寫好了!!!!!

代碼原網站

button.addEventListener('click', (e)=>{
     $.ajax({ // 這個名字跟ajax沒有半毛錢關係,ajax是ajax,jsonp是jsonp
     url: "http://jack.com:8002/pay",
     dataType: "jsonp",
     success: function( response ) {
         if(response === 'success'){
         amount.innerText = amount.innerText - 1
         }
     }
     })
    
     $.jsonp()
})
複製代碼

面試題:

請問JSONP爲何不能發POST請求?
第一句話: 由於JSONP是經過動態建立script實現的。
第二句話: 動態建立script的時候只能用GET,不能用POST


  • onload:onload 事件會在頁面或圖片加載完成後當即發生。
  • onerror:onerror 事件會在文檔或圖像加載過程當中發生錯誤時被觸發。 在裝載文檔或圖像的過程當中若是發生了錯誤,就會調用該事件句柄。
  • alert():顯示一個警告對話框,上面顯示有指定的文本內容以及一個"肯定"按鈕。
  • Location.reload():用來刷新當前頁面。
           該方法只有一個參數,當值爲 true時,將強制瀏覽器從服務器加載頁面資源,當值爲 false 或者未傳參時,瀏覽器則可能從緩存中讀取頁面。
           該方法在跨域調用(執行該方法的腳本文件的域和 Location 對象所在頁面的跨不一樣)時,將會拋出 DOMException 異常。
  • ASP Response 對象:於從服務器向用戶發送輸出的結果。ASP其他對象參考連接 response.write():向輸出寫指定的字符串。
    response.end():中止處理腳本,並返回當前的結果。
    response.setHeader(name, value):例如response.setHeader('Content-Type', 'text/html');
    response.statusCode = 2xx/3xx/4xx/5xx :此屬性控制在刷新響應頭時將發送到客戶端的狀態碼。
  • node.js:Node.js就是這樣一個服務器端的、非阻斷式I/O的、事件驅動的JavaScript運行環境。(去茶葉鋪賣茶葉例子)
    Node.js的應用是經過javascript開發的,而後直接在Google的變態V8引擎上跑。用了Node.js,你就不用擔憂用戶端的請求會在服務器裏跑了一段可以形成阻塞的代碼了。由於javascript自己就是事件驅動的腳本語言。
           服務器端JavaScript處理:server-side JavaScript execution
           非阻斷/異步I/O:non-blocking or asynchronous I/O
           事件驅動:Event-driven
  • 佔位符:&&&amount&&& 這是一個特殊的佔位符,總體都是,爲了表示這是個人佔位符,別人別碰。
  • fs: fsfilesystem的縮寫,該模塊提供本地文件的讀寫能力,基本上是POSIX文件操做命令的簡單包裝。可是,這個模塊幾乎對全部操做提供異步和同步兩種操做方式,供開發者選擇。 FS講義 FS文檔
異步 fs.readFile(文件的路徑, 讀取完成後的回調函數)
同步 fs.readFileSync(文件路徑,'utf8')

     fs.readFileSync()的第二個參數能夠是一個表示配置的對象,也能夠是一個表示文本文件編碼的字符串。
     默認的配置對象是{ encoding: null, flag: 'r' },即文件編碼默認爲null,讀取模式默認爲r(只讀)。
     若是第二個參數不指定編碼(encoding),readFileSync方法返回一個Buffer實例,不然返回的是一個字符串。
     
     Buffer對象是Node處理二進制數據的一個接口,它是Node原生提供的全局對象,能夠直接使用。
     buffer文檔:https://javascript.ruanyifeng.com/nodejs/buffer.html

複製代碼
  • form(html標籤): 一旦提交,就刷新當前頁面
action="URL" 規定當提交表單時向何處發送表單數據。
method="get/post" 規定用於發送 form-data 的 HTTP 方法。 
target="" 規定在何處打開 action URL。
複製代碼
  • input: 用於蒐集用戶信息。根據不一樣的 type 屬性值,輸入字段擁有不少種形式。輸入字段能夠是文本字段、複選框、掩碼後的文本控件、單選按鈕、按鈕等等。 value="xxx" 規定input元素的值是xxx
相關文章
相關標籤/搜索