[第九週]透過瀏覽器交換資料
表單、AJAX、XMLHttpRequest

MiaHsu
8 min readMay 1, 2020

--

學習目標:了解透過 node.js 與瀏覽器發出 require 兩者之間的差異,以及使用瀏覽器傳送資料的方式。

在下面兩篇學習紀錄

了解網頁是透過從 client 端發出 request 後,sever 端回傳的一大堆 response 所構成,而當然不是要什麼都給,會透過 API(是一種交換資訊的管道)獲取限定的資料。

而瀏覽器其實只是一個程式

這邊在複習一下「從輸入網址後到看到網頁發生的事情」

  1. 瀏覽器接收到 user 輸入的資訊。
  2. 發出網路請求。
  3. DNS 開始將 url 解析成 IP 位置。
  4. 解析成功建立網路連線。
  5. server 端收到 request 後,回傳 response。
  6. 瀏覽器開始解析 response 檔案(就是 html 格式的檔案)。
  7. 在解析的過程中,如果遇到 CSS JS 圖片檔案等,就再發送 request ,server 回傳 response,反覆傳送。
  8. 發送完所有資源的 request 後開始下載資源。
  9. 進行渲染網頁。

上述的過程可以知道,response 的檔案不限定於某幾種,因此 json 格式也可以是個 response 檔案(例如:https://reqres.in/api/users

node.js 與瀏覽器發 request 兩者之間的差異

在前幾週我們是透過 node.js 的 request 套件發出 request,那這種方法跟使用瀏覽器兩者之間到底有什麼差異呢?

node.js :沒有任何限制與干擾,傳什麼就回什麼

「直接」將 request 傳送到 server 端,因此不會有任何限制與干擾。

瀏覽器:可能會阻止做某些事或加某些東西

「透過瀏覽器」將 request 傳送到 server 端,而瀏覽器基於安全性的考量會有某些限制與規範(同源政策、CORS等),可能會阻止做某些事或加某些東西(例如:增加瀏覽器的版本)。

因為這些差異導致我們在從瀏覽器發送 request 時有些規則需要學習

網頁前端傳資料到後端的方式

第一種 form

  • 最陽春的方式,跟 JavaScript 一點關係都沒有,比較像是我要到這個頁面,那要帶什麼東西才能到這個頁面。
  • GETPOST 兩種傳送方式,登入的話會用 POST
    GET 會將參數附加在網址後方,因此參數會外顯。
    POST會將參數放在 request 內。
  • 特性:會換頁並直接 random response。
  • 缺點:每一次都要換頁
  • 範例
<form action="/test" method="get">   <input type="text" name="username" id="username">姓名   <input type="submit" value="送出"></form>

按下送出後,會轉址到 action (範例是使用 GET 如果用 POST 一樣會轉址,
但不會顯示參數)

範例程式碼是發到 /test ,因為沒有這個檔案,所以頁面顯示找不到

如果是發送到 https://google.com 呢?

會跳轉到頁面並在後方加上參數。

第二種 AJAX

  • 特性:將資料轉傳到 JavaScript ,就可以解決表單換頁的問題。
  • 注意!html 的內容會是空的,因為我們是用 JavaScript 動態產生內容,因此對於搜尋引擎來說,會認為這個網頁是沒有內容的。
以下內容大部分取自文章: Huli 輕鬆理解 Ajax 與跨來源請求

全名 Asynchronous JavaScript and XML ,中文翻譯為「非同步的 JavaScript 與 XML 技術」。

了解這項技術前,首先要先知道什麼是「非同步的 JavaScript」。

什麼是同步?什麼是非同步

指的是 JavaScript 的「執行順序」

  • 同步:會先等這行程式執行完畢並得到「結果」才繼續往下執行,確保執行順序。
  • 非同步:執行後就不管他了,不等「結果」回來就繼續往下執行。

一般來說同步的 JavaScript 是非常合理的,但當牽涉到網路、交換資料就不能同日而論,我們將 reponse 替換結果,套入上述兩句話中:

  • 同步:會先等這行程式執行完畢並得到「reponse」才繼續往下執行,確保執行順序。
  • 非同步:執行後就不管他了,不等「reponse」回來就繼續往下執行。

當牽涉到網路、交換資料時,如果是「同步」的 JavaScript ,要等 reponse 回傳才會往下執行,代表說在這期間,點任何牽涉到 JavaScript 的東西都不會有任何反應,因為還在等前面的 Reponse 回來,老天鵝這不太對,人家會以為網站掛掉了吧!因此對於傳遞資料必須使用「非同步」的 JavaScript 。

那怎麼能知道 reponse 後結果(資料)要傳到哪執行呢?

這邊需要特別注意的是 「非同步的 Function 不能直接透過 return 把結果傳回來」,因為執行到 return 時,結果根本來還傳回來。

因此在 [第八週]DOM — 瀏覽器事件處理 學到的 callback function 就派上用場了

當非同步的操作完成時,就可以呼叫這個 Function,並且把結果帶進來執行。

實作 AJAX

const request = new XMLHttpRequest()request.onload = function() {   if(request.status >= 200 && request.status < 400) {      console.log(request.responseText);   }else {      console.log('err');   }}request.onerror = function() {   console.log('error');}request.open('GET', 'https://reqres.in/api/users',true);request.send();

程式碼說明:

利用 AJAX送出一個 HTTP 請求,必須有三個步驟:

  1. 需要建立一個 XMLHttpRequest 物件
  • XMLHttpRequest 是一個 JavaScript 準備好的物件,主是要拿來發送 request 與接收 response
  • const request = new XMLHttpRequest()

2. 開啟一個 url .open()

  • request.open(method, url[, async[, user[, password]]])
  • 參數分別為 1⃣️Method 2⃣️URL 3⃣️同步 | 非同步 4⃣️使用者 5⃣️密碼

3. 發起一個請求 .send()

  • request.send()

這三個步驟就完成送出一個 HTTP 請求,但我們最主要的目的是拿到資料做事情,因此還要「監聽載入」拿到資料 .onload

有兩種寫法:

  1. 目標.onload = function(){ … }
  2. 目標.addEventListener(‘load’,function(){ … })

可使用相關 api

  • .responseText:拿到資料
  • .status:拿到 Http status code 狀態碼

範例程式碼是發到 https://reqres.in/api/users ,回傳以下結果

成功得到資料

換發 request 到 https://google.com ,結果:回傳錯誤訊息,以下為錯誤訊息:

ajax.html:1 Access to XMLHttpRequest at 'https://google.com/' from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

意思指由於瀏覽器有安全性考量,有一個東西叫同源政策(Same-origin policy),他不准我們發 request 到 https://google.com/

請繼續服用下集: [第九週]透過瀏覽器交換資料 — 同源政策、CORS、第三種方式 JSONP

以上有錯誤的地方歡迎指正,感謝。

--

--

MiaHsu

每件事都是最好的安排,成為更好的自己