XMLHttpRequest 的寫法

覺得太久沒寫的話又會忘記它的寫法。

簡述

這邊是用這支 API 來做示範。

GET

簡單來說順序一定是這樣:

  1. 建立 XHR 實體
  2. 打開要請求的 end point
  3. 設定拿到回應的 callback
  4. 發送 request 失敗的 callback
  5. 送出 request
1
<button>Send request</button>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
function sendRequest(url, callback) {
// 建立 xhr 實體
const request = new XMLHttpRequest()
// 設定 end point 跟 HTTP method
request.open('GET', url, true)
// 有需要加上 header 的話
request.setRequestHeader('client-id', 'xxxxxx')
// 請求成功的 callback
request.onload = () => {
if (request.status >= 200 && request.status < 400) {
callback(null, request.responseText)
} else {
callback('We reached our target server, but it returned an error')
}
}
// 請求失敗的 callback
request.onerror = () => {
callback('There was a connection error of some sort')
}
// 送出請求
request.send()
}

// 按下按鈕就發一個 request
const URL = 'https://gorest.co.in/public/v1/users'
const button = document.querySelector('button')

button.onclick = () => {
sendRequest(URL)
.then(data => console.log(JSON.parse(data)))
.catch(err => console.log(err))
}

備註:onerror 的定義是你連 request 都沒有送出去,伺服器根本沒收到的意思。

POST

跟剛剛差不多,但要注意 POST 的資料格式:

  • application/json JSON
  • application/x-www-form-urlencoded Form

這邊示範 JSON:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
function sendRequest(url) {
return new Promise((resolve, reject) => {
// 要傳送的 JSON 資料
const params = {
email: 'aaa123456@gmail.com',
gender: 'male',
name: 'Jacky',
status: 'active'
}
const request = new XMLHttpRequest()
request.open('POST', url, true)
request.setRequestHeader('Content-type', 'application/json')
request.setRequestHeader('Authorization', 'Bearer xxxxx')
request.onload = () => {
if (request.status >= 200 && request.status < 400) {
resolve(request.responseText)
} else {
reject('We reached our target server, but it returned an error')
}
}
request.onerror = () => {
reject('There was a connection error of some sort')
}
// 最後要記得轉成字串
request.send(JSON.stringify(params))
})
}

// 按下按鈕就發一個 request
const URL = 'https://gorest.co.in/public/v1/users'
const button = document.querySelector('button')

button.onclick = () => {
sendRequest(URL)
.then(data => console.log(JSON.parse(data)))
.catch(err => console.log(err))
}

Form 表單:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
function sendRequest(url) {
return new Promise((resolve, reject) => {
const request = new XMLHttpRequest()
request.open('POST', url, true)
// 記得資料格式要填對
request.setRequestHeader('Content-type', 'application/x-www-form-urlencoded; charset=UTF-8')
request.setRequestHeader('Authorization', 'Bearer xxxxx')
request.onload = () => {
if (request.status >= 200 && request.status < 400) {
resolve(request.responseText)
} else {
reject('We reached our target server, but it returned an error')
}
}
request.onerror = () => {
reject('There was a connection error of some sort')
}
// 用 queryString 的格式來送資料
request.send('email=bbb123456@gmail.com&gender=male&name=Jacky&status=active')
})
}

// 按下按鈕就發一個 request
const URL = 'https://gorest.co.in/public/v1/users'
const button = document.querySelector('button')

button.onclick = () => {
sendRequest(URL)
.then(data => console.log(JSON.parse(data)))
.catch(err => console.log(err))
}

或其實也可以用 FormData 來設定資料:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
function sendRequest(url) {
return new Promise((resolve, reject) => {
let form = new FormData()
form.append('email', 'apple123456@gmail.com')
form.append('gender', 'male')
form.append('name', 'yoyo')
form.append('status', 'active')

/* 要檢查內容得這樣看 */
/* for (var [key, value] of data.entries()) {
// console.log(key, value);
} */

const request = new XMLHttpRequest()
request.open('POST', url, true)
request.setRequestHeader('Authorization', 'Bearer xxxx')
request.onload = () => {
if (request.status >= 200 && request.status < 400) {
resolve(request.responseText)
} else {
reject('We reached our target server, but it returned an error')
}
}
request.onerror = () => {
reject('There was a connection error of some sort')
}
// 最後把建立好的 form 送出去
request.send(form)
})
}


const URL = 'https://gorest.co.in/public/v1/users/'
const button = document.querySelector('button')

button.onclick = () => {
sendRequest(URL)
.then(data => console.log(JSON.parse(data)))
.catch(err => console.log(err))
}

備註:我這邊實測會拿到 422 (POST 內容不對)錯誤,但我確認過格式沒錯呀。總之呢,知道能這樣用就好。

補充:為什麼會失敗?

因為這一段:

1
request.setRequestHeader('Content-type', 'application/x-www-form-urlencoded')

如果要用 FormData 來包裝表單,xhr 會自己幫你設定正確的 Content-type,但如果我們自己又加上 header 的話會把原本的給覆寫掉,所以只要拿掉那一段就 OK 了。

mentor-program-day48 什麼是 JSONP
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×