close

在 JavaScript 中,promise 是一個正在進行操作的值的占位符。

你通常使用一個 promise 來管理你必須等待操作結果的情況。例如,將文件上傳到服務器並等待 API 調用的響應,或者只是要求用戶從他們的計算機中選擇一個文件。

在這篇文章中,你將通過建立一個像下面這樣的真實世界的例子應用來學習 JavaScript 的 promise。

Promise 是什麼

promise 是一個簡單的函數,它返回一個你可以回調的 Object(對象)。

promise 對象上的回調只有在操作完成時才會被調用。在之前,回調將不得不等待,直到操作被fulfilled 或 rejected:

fetch(`some_api_url`).then((response)=>{//這裡的將等待獲取操作的完成});

在一個 promise 最終確定之前( promise 要麼實現(fulfills),要麼被拒絕(rejected)),它必須經歷不同的狀態:

StateDescriptionCallbcakpending意味着操作仍在運行,promise 正在等待中-fulfilled操作已經完成,並且很成功.then()rejected操作已完成,但出現了一個錯誤.catch()settledpromise 要麼已經 fulfilled ,要麼被 rejected,無論如何,這個回調都會被調用.finally()

當一個 promise 被創建時,初始狀態是待定(pending)。然後根據操作的輸出,promise 要麼被 fulfilled,要麼被 rejected。

從上面的表格中,你可以很容易地看到根據 Promise 的每個狀態而被調用的回調:

fetch(`some_api_url`).then((response)=>{//當promisefulfilled 時,這將被調用}).catch((error)=>{//當promiserejected 時,這將被調用}).finally(()=>{//這將在最後面調用})如何在 JavaScript 中使用 Promises

現在你已經了解了什麼是 promise,讓我們通過建立我們之前看到的電影搜索應用來演示如何在 JavaScript 中使用 promise。

一個基本的電影搜索應用程序應該有一個輸入字段,用戶可以在那裡搜索他們喜歡的電影。它還應該有一個用戶界面來顯示他們所搜索的電影的一些基本信息。

讓我們從創建 HTML 開始。

如何編寫 HTML

為了本教程的目的和提供實際的例子,我將使用 Codepen,但你可以使用你喜歡的代碼編輯器。

創建一個index.html文件並添加以下代碼:

<divclass="wrapper"><headerclass="header"><divclass="header_logo">Movie</div><divclass="header_actions"><formonsubmit="handle_form(event)"id="header_form"><divclass="header_form-icon"><inputtype="search"class="header_form-input"placeholder="Search,PressEntertoSubmit"/><svgclass="icon"width="22px"height="22px"><usehref="#icon-search"/></svg></div></form><imgid="img_icon"width="32px"height="32px"src=""alt=""></div></header><mainid="main"><section><articleclass="movie"><divclass="movie_img"><imgid="img_src"src=""alt=""srcset=""></div><divclass="movie_info"><header><h1class="movie_title"></h1></header><divclass="movie_desc"></div><divclass="movie_details"><h2>Details</h2><ulclass="flex"><li>Premiered:<spanid="movie_date"></span></li><li>Rating:<spanid="movie_rating"></span></li><li>Runtime:<spanid="movie_runtime"></span></li><li>Status:<spanid="movie_status"></span></li></ul></div><ahref=""class="btn"target="_blank"rel="noopenernoreferrer"><svgclass="icon"width="16px"height="16px"><usehref="#icon-play"/></svg>WatchMovie</a></div></article><divclass="episodes_list"><h3class="episodes_title"></h3><olclass="episodes"id="episodes"></ol></div></section></main></div>

上面我們只是創建了我們的電影應用程序的基礎。所以現在讓我們用一些 CSS 給它注入一些活力。

如何獲取電影

為了獲取我們的電影,我們將使用 TVMAZE 的 API。創建main.js文件並添加以下代碼:

constget_movie=(value="Gameofthrones")=>{fetch(`https://api.tvmaze.com/singlesearch/shows?q=${value}&embed=episodes`).then((response)=>create_UI(response.json()));};

我們創建了一個函數get_movie(value = "Game of thrones"),使用了 JavaScript fetch API。我們用它來向我們的電影 API 端點(endpoint)發出GET請求。

fetch API 會返回一個 promise 。為了使用 API 的響應,我們使用了.then()回調,其中我們將response.json()傳入一個新的函數create_UI()。讓我們繼續創建create_UI函數:

constcreate_UI=(data)=>{constmovie_img=document.querySelector("#img_src");constmovie_icon=document.querySelector("#img_icon");constmovie_title=document.querySelector(".movie_title");constmovie_desc=document.querySelector(".movie_desc");constmovie_link=document.querySelector(".btn");constmovie_date=document.querySelector("#movie_date");constmovie_rating=document.querySelector("#movie_rating");constmovie_runtime=document.querySelector("#movie_runtime");constmovie_status=document.querySelector("#movie_status");//設置 UImovie_icon.src=data.image.medium;movie_img.src=data.image.original;movie_title.textContent=data.name;movie_desc.innerHTML=data.summary;movie_link.href=data.officialSite;movie_date.textContent=data.premiered;movie_rating.textContent=data.rating.average;movie_runtime.textContent=data.runtime;movie_status.textContent=data.status;};

上述函數,顧名思義,幫助我們為我們的電影應用程序創建用戶界面。但當然,我們仍然需要一種方法來收集用戶的電影名稱。

我們需要做的第一件事是給我們的 HTML 表單(form)添加一個onsubmit事件處理程序:

<formonsubmit="search(event)"id="header_form"><inputtype="search"class="header_form-input"placeholder="Search,PressEntertoSubmit"/>//</form>

現在在我們的main.js文件中,我們通過提交表單時發生的事件觸發處理:

//handleformsubmitconstsearch=(event)=>{event.preventDefault();constvalue=document.querySelector(".header_form-input").value;get_movie(value);};

當用戶提交表單時,我們就會得到他們在搜索框中輸入的值,並將其傳遞給我們先前創建的 get_movie(value = "Game of thrones")函數。

Promise 鏈

與我們在之前的例子中看到的不同,.then()回調並不是真正的結束。這是因為當你返回一個 promise 的值時,你會得到另一個 promise。當你想按順序運行一系列的異步操作時,這就變得非常有用。

例如,我們的電影 API 不只是返回一部電影的信息,它還返回所有劇集的信息。比方說,我們真的不想顯示《權力的遊戲》中的所有劇集,我們只想要前四(4)集。

通過 promise chaining(鏈),我們可以很容易地實現這一點:

constget_movie=(value="Gameofthrones")=>{fetch(`https://api.tvmaze.com/singlesearch/shows?q=${value}&embed=episodes`).then((response)=>response.json()).then((data)=>{if(data._embedded.episodes.length>0){constnew_data=data._embedded.episodes.slice(0,4);create_UI(data);returncreate_episodesUI(new_data);}else{returncreate_UI(data);}});};

這仍然是我們的get_movie()函數,但這次我們不是將數據傳遞給create_UI函數,而是返迴響應.then((response) => response.json())。這將創建一個新的 promise,我們可以將更多的回調添加到這個 promise 上。

理想情況下,這個鏈可以一直持續下去,只要你想。記住,你所要做的就是返回 promise 的值。

如何處理 Promises 中的錯誤

在一個 promise 中發生的錯誤會立即進入 .catch()` 回調:

fetch(`https://api.tvmaze.com/singlesearch/shows?q=${value}&embed=episodes`).then((response)=>response.json()).then((data)=>{//這裡的任何錯誤都會觸發.catch()的回調。}).catch((error)=>{//所有的錯誤都在這裡被捕捉和處理})

.catch()回調是.then(null, (error) => {})的簡寫。你也可以把上面的內容寫成:

fetch(`https://api.tvmaze.com/singlesearch/shows?q=${value}&embed=episodes`).then((response)=>response.json()).then((data)=>{//這裡的任何錯誤都會觸發.catch()的回調。},(error)=>{//所有的錯誤都在這裡被捕捉和處理})

以我們的電影搜索應用為例,當我們遇到任何錯誤時,我們可以在.catch()回調中處理並向用戶顯示一個漂亮的錯誤信息:

constget_movie=(value="Gameofthrones")=>{fetch(`https://api.tvmaze.com/singlesearch/shows?q=${value}&embed=episodes`).then((response)=>response.json()).then((data)=>{if(data._embedded.episodes.length>0){constnew_data=data._embedded.episodes.slice(0,4);create_UI(data);returncreate_episodesUI(new_data);}else{returncreate_UI(data);}}).catch((error)=>{console.log(error.message);//挑戰:在此顯示你的錯誤});};

現在,如果由於任何原因產生的一個錯誤,.catch()回調被調用,我們向用戶顯示當前的錯誤。

如何在 JavaScript 中創建 Promises

現在我們已經了解了什麼是 promise 以及如何使用它們,讓我們看看如何在 JavaScript 中創建一個 promise。

要在 JavaScript 中創建一個 promise,你需要使用 promise 構造函數。構造函數需要一個參數:一個有兩個參數的函數,resolve和reject:

constis_true=trueconstnew_promise=newPromise((resolve,reject)=>{if(is_true){//一切都很順利resolve()}else{//Oops有一個錯誤reject()}})

然後我們可以通過回調來使用我們的 new_promise:

new_promise.then((response)=>{//一切都很順利}).catch((error)=>{//處理錯誤});總結

在本教程中,我們學習了 promise,它們是什麼,以及如何通過建立一個電影搜索應用程序來使用它們。我們的電影應用程序的全部代碼和實時預覽可以在 Codepen 上找到。電影搜索應用程序。

挑戰

在創建我們的電影應用程序時,我遺漏了一些部分,我認為這些部分對你練習新的 Promise 技能很有幫助:

當我們在等待 API 響應時,我們的電影應用看起來被凍結了。你可以嘗試添加一個加載器,告訴用戶 promise 正在等待。
我們目前只是使用console.log(error)來記錄錯誤。但是我們不希望這樣,所以你可以想辦法以一種友好的方式向用戶顯示所有的錯誤。

希望這篇文章對你有幫助。

原文鏈接:https://www.freecodecamp.org/news/javascript-promises-for-beginners/

作者:Spruce Emmanuel

譯者:luojiyin

在線貢獻者交流會預告
在線貢獻者交流會將於北京時間 2022 年 9 月 11 日周日上午 10:00 - 11:00 開展(每兩周一次,都在這個時間段開展)。
歡迎大家添加小助手微信 fcczhongguo,加入會議室。
開源公益社區 freeCodeCamp.org 自 2014 年成立以來,以「幫助人們免費學習編程」為使命,創建了大量免費的編程教程,包括交互式課程、視頻課程、文章等。我們正在幫助全球數百萬人學習編程,希望讓世界上每個人都有機會獲得免費的優質的編程教育資源,成為開發者或者運用編程去解決問題。
✨ ✨ ✨
年度總結丨2021 年世界各地的開發者在 freeCodeCamp 學習 21 億分鐘(4000 年)
freeCodeCamp 教育公益下一個目標:免費提供大學計算機科學學士學位
參與 freeCodeCamp 開源社區翻譯協作,幫助全世界人們用母語免費學習編程

點擊「閱讀原文」
在freeCodeCamp 專欄了解更多
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 鑽石舞台 的頭像
    鑽石舞台

    鑽石舞台

    鑽石舞台 發表在 痞客邦 留言(0) 人氣()