【譯】用開發實例教你掌握 Async/Await

說明: 我翻譯本身讀過的文章,僅僅只是我做爲一個新手的一種學習方式。不少專業化的表達可能不是很是準確!文章中或許有翻譯錯誤的地方,若是你看到了,但願能夠在評論中指出,我會及時修正。對於大佬的你請直接忽視跳過,一樣是小白的你,能夠考慮看看。固然若是有能力,我強烈建議你直接看原文前端


目錄

  1. 介紹回調函數, promises, async/await
  2. 現實開發中的一個案例——能夠從兩個 API 異步獲取數據的貨幣轉換器

在開始正文以前

在寫這篇文章的同時,我還錄製了一個相關的視頻,已上傳到 Youtube。 你能夠邊看視頻邊敲代碼,我建議你先看下視頻,而後再以這篇文章爲引導本身練習下代碼。ios

視頻地址:Learn Async/Await in This Real World Projectgit

簡介

Async/Await 是一種創建在 promises 基礎上的,書寫異步代碼的新方式,因此它也是非阻塞的。github

與咱們以前異步編程所使用到的回調函數和 promises 相比較,最大的區別就是 async/await 使咱們的異步代碼看起來就像同步代碼同樣,這也正是它的厲害之處。npm

使用回調函數

setTimeout(() => {
  console.log('This runs after 1000 milliseconds.');
}, 1000);
複製代碼

回調函數最典型的問題——回調地獄

在回調函數中嵌套回調函數,看起來就像這樣:編程

回調地獄

回調地獄

指的是回調函數被嵌套在另外一個回調函數中,嵌套層級有多層,使咱們的代碼可讀性和可維護性變得很是差。axios

使用 Promises

const promiseFunction = new Promise((resolve, reject) => {
  const add = (a, b) => a + b;
  
  resolve(add(2, 2));
});

promiseFunction.then((response) => {
  console.log(response);
}).catch((error) => {
  console.log(error);
});
複製代碼

promiseFunction 這個函數返回一個表示函數運行過程的 Promise 對象, resolve 函數表示任務已經完成。api

而後,咱們就能夠在 promiseFunction 函數的基礎上調用 then()catch() 方法。數組

then: Promise 成功後執行的回調函數。
catch: 當遇到了錯誤後執行的回調函數。promise

Async 函數

Async函數爲咱們提供了簡潔的語法,咱們能夠經過它實現與 Promise 相同的效果,可是代碼量會減小不少。其實底層原理上,async 不過是 promises 的語法糖而已。

在普通的函數聲明前加上 async 關鍵字,咱們就建立了一個 async 函數:

const asyncFunction = async () => {
  // Code
}
複製代碼

異步函數使用 await 表達式能夠暫停函數的執行,await 關鍵字只能在 async 函數中使用,它會返回 Promise 對象的處理結果。

promises 和 async/await 的區別:

// Async/Await
const asyncGreeting = async () => 'Greetings';

// Promises
const promiseGreeting = () => new Promise(((resolve) => {
  resolve('Greetings');
}));

asyncGreeting().then(result => console.log(result));
promiseGreeting().then(result => console.log(result));
複製代碼

Async/Await 更易於咱們理解,由於它看起來像同步代碼。

前面咱們已經介紹過這些基礎知識了,如今咱們來看看在現實開發中怎麼使用!

貨幣轉換器

項目說明和初始化

在下面的教程中,咱們將建立一個簡單實用,並且頗有學習意義的應用程序,相信會加深你對 Async/Await 理解

咱們將原始貨幣代碼和想要獲得的貨幣代碼,以及金額輸入程序,而後程序會調用相關的 API,最後將正確的匯率顯示出來

在這個程序中,咱們將從如下兩個 API 異步獲取數據:

  1. Currency Layer —— currencylayer.com - 你須要先免費註冊帳號,才能獲取 API Access Key。這個 API 爲咱們提供了 計算貨幣間匯率所需的數據。
  2. Rest Countries —— restcountries.eu/ - 這個 API 爲咱們提供了給定一種貨幣,返回該貨幣在哪些國家流通

首先,建立一個新目錄並運行 npm init 初始化項目,接下里咱們選擇默認值,跳過全部步驟,而後再輸入 npm i——save axios 安裝 axios。在當前文件夾內建立一個 currency-convert .js 的文件。

currency-convert .js 文件中,咱們先經過 require 語法引入 axios

const axios = require(‘axios’);` 複製代碼

深刻理解 async/await

這個程序中,咱們須要三個異步函數,第一個函數用來獲取關於貨幣的數據;第二個函數用來獲取關於國家的數據;第三個函數用來將全部信息集中起來並展現給用戶看

第一個函數——異步獲取有關貨幣的數據

咱們建立一個接收兩個參數(fromCurrency 和 toCurrency)的異步函數。

const getExchangeRate = async (fromCurrency, toCurrency) => {}
複製代碼

如今咱們獲取數據,而後經過使用 async/await,能夠直接將咱們想要的數據賦值給變量。調用接口以前別忘了要註冊帳號,才能得到 API access key

const getExchangeRate = async (fromCurrency, toCurrency) => {
  const response = await axios.get('http://data.fixer.io/api/latest? access_key=[yourAccessKey]&format=1');
}
複製代碼

咱們能夠經過 response.data.rates 來提取咱們想要的數據,而後咱們將它賦值給一個變量 rate

const rate = response.data.rates;
複製代碼

由於全部的數據都是從歐元轉換過來的,咱們能夠建立一個變量 euro,它的值等於:

const euro = 1 / rate[fromCurrency];
複製代碼

最後,咱們能夠用歐元乘以咱們要兌換的貨幣來獲得匯率:

const exchangeRate = euro * rate[toCurrency];
複製代碼

最終的函數看起來像這樣:

第二個函數——異步獲取國家數據

建立一個異步函數,接收 currencyCode 做爲參數

const getCountries = async (currencyCode) => {}
複製代碼

和以前同樣,獲取數據,而後將其賦值給一個變量:

const response = await axios.get(`https://restcountries.eu/rest/v2/currency/${currencyCode}`);
複製代碼

而後經過數組 map 方法將 country.name 提取出來,映射爲一個新的數組:

return response.data.map(country => country.name);
複製代碼

最終代碼:

最後一個函數——將前面的函數組合起來

建立一個異步函數,接收 fromCurrency, toCurrency, amount 三個參數:

const convert = async (fromCurrency, toCurrency, amount) => {}
複製代碼

第一步,獲取貨幣數據:

const exchangeRate = await getExchangeRate(fromCurrency, toCurrency);
複製代碼

第二步,獲取國家數據:

const countries = await getCountries(toCurrency);
複製代碼

第三步,將轉換後的金額賦值給一個變量

const convertedAmount = (amount * exchangeRate).toFixed(2);
複製代碼

最後,將數據輸出給用戶:

return `${amount} ${fromCurrency} is worth ${convertedAmount} ${toCurrency}. You can spend these in the following countries: ${countries}`;
複製代碼

最後完整的代碼:

使用 try/catch 來處理錯誤

咱們將程序的邏輯用 try 語句包裹起來,若是出現錯誤,用 catch 語句捕捉:

const getExchangeRate = async (fromCurrency, toCurrency) => {
  try {
    const response = await       axios.get('http://data.fixer.io/api/latest?access_key=f68b13604ac8e570a00f7d8fe7f25e1b&format=1');
    
    const rate = response.data.rates;
    const euro = 1 / rate[fromCurrency];
    const exchangeRate = euro * rate[toCurrency];
    
    return exchangeRate;
  } catch (error) {
    throw new Error(`Unable to get currency ${fromCurrency} and ${toCurrency}`);
  }
};
複製代碼

一樣第二個函數也這樣處理:

const getCountries = async (currencyCode) => {
  try {
    const response = await axios.get(`https://restcountries.eu/rest/v2/currency/${currencyCode}`);
    
return response.data.map(country => country.name);
  } catch (error) {
    throw new Error(`Unable to get countries that use ${currencyCode}`);
  }
};
複製代碼

由於第三個函數只是處理第一個和第二個函數的結果,因此咱們不須要對它進行錯誤捕獲

最後,咱們調用函數來接收數據:

convertCurrency('USD', 'HRK', 20)
  .then((message) => {
    console.log(message);
  }).catch((error) => {
    console.log(error.message);
  });
複製代碼

你會看到下面的結果:

結束

很不錯,你堅持到了最後!若是在學習過程當中遇到了困惑的地方,你能夠參考這個倉庫裏的代碼。若是你有任何問題,能夠在下面留言。你也可關注個人 Youtube 專欄,我會帶來更多幹貨給你們!

相關文章
相關標籤/搜索