JavaScript 如何使用 fetch() 與后端交互
fetch() 是現(xiàn)代 JavaScript 自帶的函數(shù), 用來(lái)實(shí)現(xiàn)與后端的交互。比如,用來(lái)實(shí)現(xiàn)不重新加載網(wǎng)頁(yè)頁(yè)面,也可以更新網(wǎng)頁(yè)內(nèi)容,這種技術(shù)過(guò)去叫做 AJAX。?
目前,大部分網(wǎng)頁(yè)瀏覽器都支持 fetch() 了。 過(guò)去, 可使用 XMLHttpRequest 對(duì)象, 或者 jQuery 的 $.ajax(), 現(xiàn)在, 則推薦使用 fetch()。為什么?是不是寫(xiě)起來(lái)比較方便?
理解 fetch() 難點(diǎn)是 Promise,以及如何實(shí)現(xiàn)前后端的交互。 下面給出一個(gè)叫做 Mimimalist Calendar 的 Flask 網(wǎng)頁(yè)應(yīng)用, 來(lái)理解 fetch() 的用法。

Mimimalist Calendar 包含了前端代碼(templates/calendar.html)與后端代碼(app.py), 不需要知道 Promise、async/await?也可以。Mimimalist Calendar?也不包括數(shù)據(jù)庫(kù)的讀寫(xiě)。

app.py 中定義了兩個(gè)視圖函數(shù), calendar_home() 與 make_entry(), 分別對(duì)應(yīng)路由 '/' 與 '/newentry'。 訪(fǎng)問(wèn)路由 '/', 顯示 Mimimalist?Calendar 的主頁(yè)面,其包含了一個(gè)表單,以及初始的兩條日歷。 路由 '/newentry' 需要使用 POST 方法訪(fǎng)問(wèn),接收表單提供的數(shù)據(jù),轉(zhuǎn)義,最后返回一個(gè) JSON 對(duì)象,包括日歷的日期、描述、字符數(shù)。

templates/calendar.html 使用 Jinja2 模板編寫(xiě)。 定義了一張表單(id 為 form01),表單中含有兩個(gè)輸入框,分別用來(lái)輸入日歷日期與日歷描述,還有一個(gè) Add 按鈕, 點(diǎn)擊按鈕后把新的日歷添加到已有的日歷中。 日歷用一個(gè)列表(ul)表示,id 是 event-list。 重點(diǎn)是,點(diǎn)擊 Add 按鈕后,我們不希望重新加載 calendar.html。 這時(shí) fetch() 就派上用場(chǎng)了。 fetch() 在自定義的 JavaScript 函數(shù) add_new_event() 中被調(diào)用, 見(jiàn)第 35 行。?fetch() 的第一個(gè)參數(shù)是后端路由,即 '/newentry'。 第二個(gè)參數(shù)是一個(gè)對(duì)象, 包含了如下信息: method 是 POST, body 是表單對(duì)象。 如果一切順利,從后端路由 '/newentry' 返回的結(jié)果會(huì)存到 response 對(duì)象(實(shí)際是個(gè) Promise)中。?接著,通過(guò) response.json() 得到從后端返回的 JSON 對(duì)象, 將該對(duì)象存到 result 變量中, 供后面取用。 第 45-48 行新增了一個(gè) <li> 標(biāo)簽,并將其添加到已有的日歷中。 使用 elem.prepend(li), 就是在日歷的最前面插入。
為了使得點(diǎn)擊 Add 按鈕后,頁(yè)面不發(fā)生跳轉(zhuǎn),需要在 add_new_event() 函數(shù)的開(kāi)頭加入 event.preventDefault(), 這個(gè)非常重要, 見(jiàn)第 32 行。 另外, <form> 標(biāo)簽中, 不需有 action 或者 method 屬性,見(jiàn)第 13 行。