JavaScript基本功修练:Day28 - Fetch练习(GET和POST请求)

今天会承接昨天AJAX的课题,了解常用来处理AJAX的语法,Fetch,以及试试用fetch来实作GET、POST请求。

fetch基本语法

Fetch是一个全域window物件,用途是送出request。当请求成功,fetch就会回传一个promise物件(状态是fulfilled),这物件内会带有response物件,里面会放有我们想抓的资料。

fetch语法:

let promise = fetch(url, [options])
  • url是要访问的网址
  • options是一堆可选的参数,例如method、header

如果只有url,没有[options],就会预设这个请求的HTTP请求方法是GET。

Fetch的语法结构与Promise非常相似,同样是用thencatch方法来处理成功和失败的结果:

fetch( 你想访问的url,{...一堆参数(可选)} )
    .then((response) => {
        //成功结果处理
    })
    .catch((error) => {
        //错误结果处理
    })

当透过fetch语法,从浏览器向服务器发出GET请求後,接下来的流程可分为两大部分。以下会用https://randomuser.me/api/去做一个简单示范,这个API会随机产生一个人的资料。

阶段1: fetch传回带有Response物件的Promise物件

fetch('https://randomuser.me/api/')
    .then((response) => {
        console.log(response); 
    })
    .catch((error) => {
        console.log(`Error: ${error}`);
    })

我们可以从statusok查看HTTP状态。ok是一个布林值,如果status是200-299,它就是true

阶段2: 从Response物件中抽取我们想抓的资料

虽然在阶段一回传了Response物件,但这不是我们想抓的资料,即是我们常常说的「回应内容主体(Response body)」,接下来我们需要使用方法来取得它。

Response有多种方法让我们取得资料(内容主体),包括我们常常用到的.json()

  • response.json():把资料转成JSON格式
  • response.text():把资料转成text格式(变成纯字串)
  • response.blob():把资料转成Blob物件
  • response.formData():把资料转成FormData物件
  • response.arrayBuffer():把资料转成二进制数组

注意,只能使用一种方法来取得资料。例如我用了.json()的方法後,不能再用另一种方法来取得资料,因为该资料已经被处理过了。

我们最常用到就是JSON格式资料,以下例子会用.json()的方法取得资料:

fetch('https://randomuser.me/api/')
    .then((response) => {
        return response.json();
    })
    .then( (response) => {
        console.log(response);
    })
    .catch((error) => {
        console.log(`Error: ${error}`);
    })

最後就取得资料了:

async/await的写法原理是一样的,以下试试用async/await去重写以上例子:

let getJSON = async(url) => {
    let response = await fetch(url);
    let JSON = await response.json();
    console.log(JSON)
}

getJSON('https://randomuser.me/api/')

Header

上面曾提及过,在fetch()里可以有两个参数,第一个是URL,第二个是一堆参数,例如methodheader等等。当中的header就是Request header,即是请求表头,它用来描述我们发出的请求,例如是请求URL、请求方法。

Header这个术语是指表头,可以分为请求表头(Request header)与回应表头(Response header),它们是一堆描述这个请求或回应的资讯。我们可以用dev tool看到这些资讯:

请求表头及回应表头的格式是有规范,否则不能被服务器或浏览器接收。以下例子示范自订一个请求表头:

let response = fetch('https://randomuser.me/api/',{
    headers: {
        Authentication: 'secret'
    }
});

但基於HTTP的准确与安全性,某些设定是不能被我们定义,只能被浏览器定义。

POST

当我们发出POST请求时,就需要用到fetch里的第二个参数,当中包括:

  • method (HTTP请求方法)
  • request body (请求主体)

当中的request body,例如可以是:

  • 字串(用JSON.stringify转成的字串)
  • FormData物件
  • Blob所传送的二进制资料

以下用六角学院的API作例子,注册後会得到一个独立编码(UUID),这个UUID是用来组成自己的API网址时用的,另外也会提供一个API token(後台登入验证码),用来验证是否有管理员身分,并能够管理个人专属的後台。

这里会示范如果新增一笔产品资料到服务器,刚才提及uuid和token是在注册六角学院的API系统时发给我的,我把它们放在一个个的变数里,但这里就不公开了。

新增一笔产品资料的API文件:

Body Parameters就是主体参数,要写在fetch(url,{...}){...}里。

以下是完整程序码:

const uuid = xxxxx
const token = xxxxx
const url = `https://course-ec-api.hexschool.io/api/${uuid}/admin/ec/product`

let headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
    "Authorization": `Bearer ${token}`,
}

//以下是API文件中提及必写的主体参数。而以下这个产品资料是六角学院提供的。
let body = {
    "title": "Abysswalker",
    "category": "T-Shirts",
    "content": "Its wearer, like Artorias himself, can traverse the Abyss.",
    "description": "This official Dark Souls shirt was designed by Nina Matsumoto and printed on soft 100% cotton shirts by Forward. Each one comes with a bonus sticker.",
    "imageUrl": ["https://images.unsplash.com/photo-1529374255404-311a2a4f1fd9?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1349&q=80"]
}

fetch(url, {
    method: "POST",
    headers: headers,
    //别忘了把主体参数转成字串,否则资料会变成[object Object],它无法被成功储存在後台
    body: JSON.stringify(body)
})
    .then(response => response.json())
    .then(json => console.log(json));

结果:

如果我新增了3次这笔资料,後台就会有3笔资料,我们也可以用"GET"的方法去查询,六角学院提供了以下的API文件:

完整程序码:

const url = `https://course-ec-api.hexschool.io/api/${uuid}/admin/ec/products`

let headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
    "Authorization": `Bearer ${token}`,
}

fetch(url, {
    method: "GET",
    headers: headers,
})
    .then( (response) => response.json())
    .then( (json) => console.log(json));

结果真的会显示3笔资料:

总结

虽然之前已经学了Promise语法,学习Fetch时不会太吃力,但认真落手实作时才发觉也有一定的难度,而且当中有些术语,例如Body parametres、Header等等也没有看懂,所以除了看文章,也真的是需要实作练习一下~

参考资料

AJAX 完整解说系列:新增、更新、删除(POST、PATCH、DELETE)
JAVASCRIPT.INFO
JacaScript | Fetch 让 ES6 拥有一对翅膀-基础教学
铁人赛:ES6 原生 Fetch 远端资料方法


<<:  让微软帮你管理人员 - Azure Activate Directory

>>:  非本科、半路转职的「软件科技职涯发展笔记」

[DAY 19]bot在线状态通知

最近bot的更新量蛮大,有时候会关掉bot方便更新程序码 为了让频道上的人知道目前bot的状态,决定...

Day 14:专案02 - PTT C_chat版爬虫01 | 爬虫简介、request和response、Requests

⚠行前通知 先前已经学过Python但想学爬虫的人可以回来罗~ 从今天起就开始大家最期待的网页爬虫的...

[Day 12] iOS 学习流水帐

Swift 语言相关的特性纪录 (算基本的东西): 可选型别: 为了避免程序运算中因所使用变数为空值...

(Day 29) DevOps Challenges

despite all the benefits we stated yesterday, toa...