什么是 REST API

REST API?是遵循根據(jù)?API 的 REST 結(jié)構(gòu)構(gòu)建內(nèi)容的 API。REST 代表 “Representational State Transfer”。它由開發(fā)人員在創(chuàng)建 API 時遵循的各種規(guī)則組成。

REST API 的優(yōu)勢

  1. 非常容易學(xué)習(xí)和理解;
  2. 它使開發(fā)人員能夠?qū)?fù)雜的應(yīng)用程序組織成簡單的資源;
  3. 外部客戶端可以輕松地在您的 REST API 上構(gòu)建,而不會出現(xiàn)任何復(fù)雜性;
  4. 它很容易擴(kuò)展;
  5. REST API 不是特定于語言或平臺的,但可以與任何語言一起使用或在任何平臺上運(yùn)行。

REST API 響應(yīng)示例

REST API 的結(jié)構(gòu)方式取決于它所針對的產(chǎn)品 ,但必須遵守 REST 的規(guī)則。

下面的示例響應(yīng)來自 Github Open API。在本教程的后面部分,我們將使用此 API 構(gòu)建 React 應(yīng)用程序。

{
"login": "hacktivist123",
"id": 26572907,
"node_id": "MDQ6VXNlcjI2NTcyOTA3",
"avatar_url": "https://avatars3.githubusercontent.com/u/26572907?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/hacktivist123",
"html_url": "https://github.com/hacktivist123",
"followers_url": "https://api.github.com/users/hacktivist123/followers",
"following_url": "https://api.github.com/users/hacktivist123/following{/other_user}",
"gists_url": "https://api.github.com/users/hacktivist123/gists{/gist_id}",
"starred_url": "https://api.github.com/users/hacktivist123/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/hacktivist123/subscriptions",
"organizations_url": "https://api.github.com/users/hacktivist123/orgs",
"repos_url": "https://api.github.com/users/hacktivist123/repos",
"events_url": "https://api.github.com/users/hacktivist123/events{/privacy}",
"received_events_url": "https://api.github.com/users/hacktivist123/received_events",
"type": "User",
"site_admin": false,
"name": "Shedrack akintayo",
"company": null,
"blog": "https://sheddy.xyz",
"location": "Lagos, Nigeria ",
"email": null,
"hireable": true,
"bio": "? Software Engineer | | Developer Advocate??|| ? Everything JavaScript",
"public_repos": 68,
"public_gists": 1,
"followers": 130,
"following": 246,
"created_at": "2017-03-21T12:55:48Z",
"updated_at": "2020-05-11T13:02:57Z"
}

當(dāng)我向以下端點(diǎn)發(fā)出請求時,上面的響應(yīng)來自 Github REST API。它返回有關(guān)名為 hacktivist123 的用戶的所有存儲數(shù)據(jù)。有了這個響應(yīng),我們可以決定如何在 React 應(yīng)用程序中展示這些信息。

利用 Fetch API 使用 API

API 是一種內(nèi)置的 JavaScript 方法,用于從服務(wù)器或 API 端點(diǎn)獲取資源。它類似于fetch()XMLHttpRequest,但 fetch API 提供了更強(qiáng)大、更靈活的功能集。

它定義了 CORS 和 HTTP Origin 標(biāo)頭語義等概念,并在其他位置取代了它們的單獨(dú)定義。

API 方法始終采用強(qiáng)制參數(shù),即要獲取資源的路徑或URL。它返回一個Promise對象,無論請求是否成功,這個Promise都會包含請求的響應(yīng)。您還可以選擇將 init options 對象作為第二個參數(shù)傳入。

獲取響應(yīng)后,可以使用幾種內(nèi)置方法來定義響應(yīng)正文的內(nèi)容及其處理方式。

Fetch API 和 jQuery Ajax 之間的區(qū)別

Fetch API 與 jQuery Ajax 的主要區(qū)別在于三個方面,它們是:

  1. 當(dāng)出現(xiàn) HTTP 錯誤時,無論響應(yīng)狀態(tài)的性質(zhì)如何,從請求返回的 Promise 都不會被拒絕。相反,它會正常解析請求,如果響應(yīng)狀態(tài)碼是 400 或 500 類型的代碼,它會設(shè)置 ok 狀態(tài)。請求只會因為網(wǎng)絡(luò)故障或某些因素阻止請求完成而被拒絕。
  2. fetch()將不允許使用跨站點(diǎn) Cookie,即您不能使用fetch()
  3. fetch()默認(rèn)情況下也不會發(fā)送 Cookie,除非您在 init 中設(shè)置了credentials選項。

Fetch API 的參數(shù)

使用 fetch() API 的基本語法

一個基本的 fetch 請求寫起來真的很簡單,看看下面的代碼:

fetch('https://api.github.com/users/hacktivist123/repos')
.then(response => response.json())
.then(data => console.log(data));

在上面的代碼中,我們從以 JSON 格式返回數(shù)據(jù)的 URL 獲取數(shù)據(jù),然后將其打印到控制臺。使用 fetch() 的最簡單形式通常只接受一個參數(shù),即你要獲取的資源的路徑,然后返回一個包含 fetch 請求響應(yīng)的 promise。此響應(yīng)是一個對象。

響應(yīng)只是常規(guī) HTTP 響應(yīng),而不是實(shí)際的 JSON。為了從響應(yīng)中獲取 JSON 正文內(nèi)容,我們必須在響應(yīng)上使用 json() 方法將響應(yīng)更改為實(shí)際的 JSON。

在 React 應(yīng)用程序中使用 Fetch API

React Apps 中使用 Fetch API 是我們通常在 javascript 中使用 Fetch API 的方式,語法沒有變化,唯一的問題是決定在我們的 React 應(yīng)用程序中的哪個位置發(fā)出 fetch 請求。大多數(shù) fetch 請求或任何形式的 HTTP 請求通常是在 React 組件中完成的。

如果您的組件是 Class Component,則可以在 Lifecycle Method 中發(fā)出此請求,如果你的組件是一個 Functional Component,可以在React Hook中發(fā)起 。

例如,在下面的代碼中,我們將在類組件中發(fā)出 fetch 請求,這意味著我們必須在生命周期方法中執(zhí)行此操作。在這種特殊情況下,我們的 fetch 請求將在生命周期方法中發(fā)出,因為我們想在 React 組件掛載后立即發(fā)出請求。componentDidMount

好的,以下是調(diào)整后的句子:

例如,在下面的代碼中,我們將在類組件中發(fā)出 fetch 請求。這意味著我們必須在生命周期方法中執(zhí)行此操作。在這種情況下,我們的 fetch 請求將在生命周期方法 componentDidMount 中發(fā)出,因為我們想在 React 組件掛載后立即發(fā)出請求。

import React from 'react';

class myComponent extends React.Component {
componentDidMount() {
const apiUrl = 'https://api.github.com/users/hacktivist123/repos';
fetch(apiUrl)
.then((response) => response.json())
.then((data) => console.log('This is your data', data));
}
render() {
return <h1>my Component has Mounted, Check the browser 'console' </h1>;
}
}
export default myComponent;

在上面的代碼中,我們正在創(chuàng)建一個非常簡單的類組件,該組件發(fā)出一個 fetch 請求,在 React 組件完成掛載后,將我們對 API URL 發(fā)出的 fetch 請求的最終數(shù)據(jù)記錄到瀏覽器控制臺中。

該方法可以獲取我們想要獲取的資源的路徑,該路徑被分配給一個名為 fetch 請求。當(dāng)請求完成后,它將返回一個包含 response 對象的 Promise。然后,我們使用該方法從響應(yīng)中提取 JSON 正文內(nèi)容,最后我們將 Promise 的最終數(shù)據(jù)記錄到控制臺中。

讓我們使用 Fetch 方法的 REST API

在本節(jié)中,我們將構(gòu)建一個使用外部 API 的簡單 react 應(yīng)用程序,我們將使用 Fetch 方法來使用 API。

這個簡單的應(yīng)用程序?qū)@示屬于特定用戶的所有存儲庫及其描述。在本教程中,我將使用我的 GitHub 用戶名,如果您愿意,您也可以使用您的用戶名。

我們需要做的第一件事是使用create-react-app生成我們的React應(yīng)用。

npx create-react-app myRepos

上面的命令將為我們引導(dǎo)一個新的 React 應(yīng)用程序。創(chuàng)建新應(yīng)用程序后,剩下要做的就是運(yùn)行以下命令并開始編碼:

npm start

如果我們的 React 創(chuàng)建正確,我們應(yīng)該在運(yùn)行上述命令后導(dǎo)航到瀏覽器窗口時看到localhost:3000

在您的文件夾中,創(chuàng)建一個名為srccomponent的新文件夾。這個文件夾將保存我們所有的 React 組件。在新文件夾中,創(chuàng)建兩個名為 List.js 和 withListLoading.js 的文件。這兩個文件將保存我們的應(yīng)用程序中需要的組件。

List.js 文件將以列表的形式處理 Repositories 的顯示,而 withListLoading.js 文件將包含一個高階組件,該組件將在我們將要發(fā)出的 Fetch 請求仍在進(jìn)行時顯示。

在我們List.js文件夾內(nèi)創(chuàng)建的文件中,讓我們粘貼以下代碼:

import React from 'react';
const List = (props) => {
const { repos } = props;
if (!repos || repos.length === 0) return <p>No repos, sorry</p>;
return (
<ul>
<h2 className='list-head'>Available Public Repositories</h2>
{repos.map((repo) => {
return (
<li key={repo.id} className='list'>
<span className='repo-text'>{repo.name} </span>
<span className='repo-description'>{repo.description}</span>
</li>
);
})}
</ul>
);
};
export default List;

上面的代碼是一個基本的 React 列表組件,它將在列表中顯示數(shù)據(jù),在本例中為存儲庫名稱及其描述。

現(xiàn)在,讓我一點(diǎn)一點(diǎn)地解釋代碼。

const { repos } = props;

我們正在為名為 repos 的組件初始化一個 prop。

if (repos.length === 0 || !repos) return <p>No repos, sorry</p>;

在這里,我們所做的只是制作一個條件語句,當(dāng)我們從發(fā)出的請求中獲得的存儲庫長度等于零時,該語句將呈現(xiàn)一條消息。

return (
<ul>
<h2 className='list-head'>Available Public Repositories</h2>
{repos.map((repo) => {
return (
<li key={repo.id} className='list'>
<span className='repo-text'>{repo.name} </span>
<span className='repo-description'>{repo.description}</span>
</li>
);
})}
</ul>
);

在這里,我們將映射我們發(fā)出的 API 請求將提供的每個存儲庫,并提取每個存儲庫名稱及其描述,然后將每個存儲庫顯示在列表中。

export default List;

在這里,我們導(dǎo)出了我們的組件,以便我們可以在其他地方使用它。

在我們 components 文件夾中創(chuàng)建的 withListLoading.js 文件中,讓我們粘貼以下代碼:

import React from 'react';

function WithListLoading(Component) {
return function WihLoadingComponent({ isLoading, ...props }) {
if (!isLoading) return <Component {...props} />;
return (
<p style={{ textAlign: 'center', fontSize: '30px' }}>
Hold on, fetching data may take some time :)
</p>
);
};
}
export default WithListLoading;

上面的代碼是一個高階 React 組件,它接受另一個組件作為參數(shù),并返回一個新的組件。在這個例子中,高階組件會等待檢查傳入的組件的狀態(tài)是否為 true。如果狀態(tài)為 true,它會顯示一條消息 “Hold on, fetching data may take some time :)”。然后,它將狀態(tài)更改為 false,并渲染傳入的組件(在這個例子中是 List 組件)。

在 src 文件夾內(nèi)的 *App.js 文件中,讓我們粘貼以下代碼:

import React, { useEffect, useState } from 'react';
import './App.css';
import List from './components/List';
import withListLoading from './components/withListLoading';
function App() {
const ListLoading = withListLoading(List);
const [appState, setAppState] = useState({
loading: false,
repos: null,
});

useEffect(() => {
setAppState({ loading: true });
const apiUrl = https://api.github.com/users/hacktivist123/repos; fetch(apiUrl) .then((res) => res.json()) .then((repos) => { setAppState({ loading: false, repos: repos }); }); }, [setAppState]); return ( <div className='App'> <div className='container'> <h1>My Repositories</h1> </div> <div className='repo-container'> <ListLoading isLoading={appState.loading} repos={appState.repos} /> </div> <footer> <div className='footer'> Built{' '} <span role='img' aria-label='love'> ?? </span>{' '} with by Shedrack Akintayo </div> </footer> </div> ); } export default App;

我們的 App.js 是一個功能組件,它使用 React Hooks 來處理狀態(tài)和副作用。如果你不熟悉 React Hooks,請閱讀我的 React Hooks 入門指南。

讓我一點(diǎn)一點(diǎn)地解釋上面的代碼。

import React, { useEffect, useState } from 'react';
import './App.css';
import List from './components/List';
import withListLoading from './components/withListLoading';

在這里,我們將導(dǎo)入所需的所有外部文件,以及我們在 components 文件夾中創(chuàng)建的組件。我們還從 React 中導(dǎo)入了我們需要的 React Hooks。

const ListLoading = withListLoading(List);
const [appState, setAppState] = useState({
loading: false,
repos: null,
});

在這里,我們正在創(chuàng)建一個名為 ListLoading 的新組件,并分配我們的高階組件。然后,我們創(chuàng)建了一個名為 loading 的狀態(tài)值,并使用 React Hook useState() 來管理它。最后,我們將這個狀態(tài)值傳遞給我們的高階組件,以便在列表加載時顯示相應(yīng)的消息。

useEffect(() => {
setAppState({ loading: true });
const user = https://api.github.com/users/hacktivist123/repos; fetch(user) .then((res) => res.json()) .then((repos) => { setAppState({ loading: false, repos: repos }); }); }, [setAppState]);

在這個 React Hook 中,我們首先將初始加載狀態(tài)設(shè)為 true。當(dāng)這個狀態(tài)為 true 時,我們的高階組件會顯示一條消息。接著,我們創(chuàng)建一個名為 NAME 的常量變量,并將其設(shè)置為我們將從中獲取存儲庫數(shù)據(jù)的 API URL。然后,我們使用 useEffect() 鉤子來處理副作用。

然后,我們像上面討論的那樣發(fā)出一個基本請求,然后在請求完成后,我們將應(yīng)用程序加載狀態(tài)設(shè)置為 false,并使用我們從請求中獲得的數(shù)據(jù)填充存儲庫狀態(tài)。

return (
<div className='App'>
<div className='container'>
<h1>My Repositories</h1>
</div>
<div className='repo-container'>
<ListLoading isLoading={AppState.loading} repos={AppState.repos} />
</div>
</div>
);
}
export default App;

在這個示例中,我們渲染了一個高階組件(HOC),它接收一個組件作為參數(shù)并返回一個新的組件。這個新的組件會使用傳入的組件的 state 值來填充 prop 和 prop。同時,isLoadingrepos 這個 prop 用于指示數(shù)據(jù)是否正在加載。由于我們使用了 withListLoading HOC,所以在 fetch 請求仍在發(fā)出時,瀏覽器將顯示相應(yīng)的加載狀態(tài)。

現(xiàn)在,當(dāng) fetch 請求成功完成時,我們應(yīng)該會看到倉庫以列表格式顯示,如下所示:

現(xiàn)在,讓我們稍微設(shè)置一下項目的樣式,在您的 App.css 文件中,復(fù)制并粘貼此代碼。

@import url('https://fonts.googleapis.com/css2?family=Amiri&display=swap');
:root {
--basic-color: #23cc71;
}
.App {
box-sizing: border-box;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
font-family: 'Amiri', serif;
overflow: hidden;
}
.container {
display: flex;
flex-direction: row;
}
.container h1 {
font-size: 60px;
text-align: center;
color: var(--basic-color);
}
.repo-container {
width: 50%;
height: 700px;
margin: 50px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
overflow: scroll;
}
@media screen and (max-width: 600px) {
.repo-container {
width: 100%;
margin: 0;
box-shadow: none;
}
}
.repo-text {
font-weight: 600;
}
.repo-description {
font-weight: 600;
font-style: bold;
color: var(--basic-color);
}
.list-head {
text-align: center;
font-weight: 800;
text-transform: uppercase;
}
.footer {
font-size: 15px;
font-weight: 600;
}
.list {
list-style: circle;
}

因此,在上面的代碼中,我們通過為App.js文件中的各個元素分配不同的類名來設(shè)置應(yīng)用程序的樣式。這使得我們的應(yīng)用程序看起來更加美觀。

修改后,我們的應(yīng)用程序應(yīng)如下所示:

現(xiàn)在我們的應(yīng)用程序看起來好多了。??

在這段代碼中,我們使用了 Fetch API 來調(diào)用 REST API。在下一節(jié)中,我們將探討如何使用 Axios 庫來實(shí)現(xiàn)相同的功能。

通過 Axios 使用 API

Axios 是一個易于使用的基于 Promise 的 HTTP 客戶端,適用于瀏覽器和 node.js。由于 Axios 是基于 promise 的,我們可以利用 async 和 await 來獲得更具可讀性和異步的代碼。使用 Axios,我們能夠攔截和取消請求,它還具有內(nèi)置功能,可提供客戶端保護(hù)以防止跨站點(diǎn)請求偽造。

Axios 的特點(diǎn)

使用 Axios 發(fā)出請求

使用 Axios 發(fā)出 HTTP 請求非常簡單。下面的代碼基本上寫出了如何發(fā)出 HTTP 請求。

// Make a GET request
axios({
method: 'get',
url: 'https://api.github.com/users/hacktivist123',
});

// Make a Post Request
axios({
method: 'post',
url: '/login',
data: {
firstName: 'shedrack',
lastName: 'akintayo'
}
});

上面的代碼顯示了我們使用 Axios 發(fā)出 GET 和 POST HTTP 請求的基本方法。

Axios 還提供了一組用于執(zhí)行不同 HTTP 請求的速記方法。方法如下:

例如,如果我們想發(fā)出一個類似的請求,就像上面的示例代碼一樣,但使用簡寫方法,我們可以這樣做:

// Make a GET request with a shorthand method
axios.get('https://api.github.com/users/hacktivist123');

// Make a Post Request with a shorthand method
axios.post('/signup', {
firstName: 'shedrack',
lastName: 'akintayo'
});

在上面的代碼中,我們發(fā)出的請求與上面所做的相同,但這次使用簡寫方法。Axios 提供了靈活性,使您的 HTTP 請求更具可讀性。

使用 Axios 發(fā)出多個請求

Axios 允許開發(fā)人員同時發(fā)出并處理多個 HTTP 請求。它通過 axios.all() 方法接受一個參數(shù)數(shù)組,并返回一個 promise 對象,該對象在所有傳入的參數(shù)都解析完成后才會解析。

例如,我們可以使用以下方式向 GitHub API 發(fā)起多個請求:

axios.all([
axios.get('https://api.github.com/users/hacktivist123'),
axios.get('https://api.github.com/users/adenekan41')
])
.then(response => {
console.log('Date created: ', response[0].data.created_at);
console.log('Date created: ', response[1].data.created_at);
});

上面的代碼通過 axios.all() 方法并行地向參數(shù)數(shù)組發(fā)出多個請求,并返回響應(yīng)數(shù)據(jù)。在我們的示例中,它會將每個 API 響應(yīng)中的對象記錄到控制臺。

讓我們在 Axios 客戶端中使用 REST API

在本節(jié)中,我們將使用 Axios 替換現(xiàn)有 React 應(yīng)用程序中的 fetch() 方法。首先,我們需要安裝 Axios,然后在 App.js 文件中使用它來向 GitHub API 發(fā)出 HTTP 請求。

現(xiàn)在讓我們通過運(yùn)行以下任一命令在我們的 React 應(yīng)用程序中安裝 Axios:

使用 NPM:

npm install axios

使用 Yarn:

yarn add axios

安裝完成后,我們必須將 axios 導(dǎo)入到我們的 App.js 中。在我們的 App.js 中,我們將以下行添加到 App.js 文件的頂部:

import axios from 'axios'

添加代碼行后在 App.js 文件中,我們可以使用 useEffect() 鉤子來處理副作用

useEffect(() => {
setAppState({ loading: true });
const apiUrl = 'https://api.github.com/users/hacktivist123/repos';
axios.get(apiUrl).then((repos) => {
const allRepos = repos.data;
setAppState({ loading: false, repos: allRepos });
});
}, [setAppState]);

您可能已經(jīng)注意到,我們現(xiàn)在已將 fetch API 替換為 Axios 速記方法,以向 API 發(fā)出請求。

axios.get(apiUrl).then((repos) => {
const allRepos = repos.data;
setAppState({ loading: false, repos: allRepos });
});

在這個代碼塊中,我們發(fā)送一個 GET 請求以獲取數(shù)據(jù),并返回一個 Promise。這個 Promise 包含名為 repos 的數(shù)據(jù),我們將這些數(shù)據(jù)分配給一個常量變量。然后,我們將當(dāng)前的加載狀態(tài)設(shè)置為 false,并將從請求中獲得的數(shù)據(jù)傳遞給名為 repos 的狀態(tài)變量。

如果我們正確地完成了所有操作,我們應(yīng)該會看到我們的應(yīng)用程序仍然以相同的方式呈現(xiàn),沒有任何變化。

這就是我們?nèi)绾问褂?Axios 客戶端來使用 REST API的方法。

Fetch 與 Axios

在本節(jié)中,我將探討 Fetch 和 Axios 對這些功能的支持程度。

  1. 基本語法
    Axios 提供了更簡潔的語法,自動將響應(yīng)轉(zhuǎn)換為 JSON,而 Fetch 需要手動轉(zhuǎn)換。此外,Axios 的速記方法使得制作特定的 HTTP 請求更加容易。
  2. 瀏覽器兼容性
    Axios 在主流瀏覽器和版本上都有很好的支持,而 Fetch 僅在 Chrome 42+、Firefox 39+、Edge 14+ 和 Safari 10.1+ 中受支持。
  3. 處理響應(yīng)超時
    Axios 通過使用請求對象中的選項輕松設(shè)置響應(yīng)超時,而在 Fetch 中實(shí)現(xiàn)這一點(diǎn)較為困難。
  4. 攔截 HTTP 請求Axios
    Axios 允許開發(fā)人員攔截 HTTP 請求,這對于需要在應(yīng)用程序和服務(wù)器之間更改 HTTP 請求的情況非常有用。
  5. 同時發(fā)出多個請求
    Axios 提供了發(fā)出多個 HTTP 請求的方法,而 Fetch 則需要額外的代碼來實(shí)現(xiàn)這一功能。

結(jié)論

Axios 和 fetch 都是很好的 API 使用方法,但在構(gòu)建小型應(yīng)用程序時,建議使用 fetch,而在構(gòu)建大型應(yīng)用程序時,出于可擴(kuò)展性考慮,推薦使用 Axios。希望這個教程對你有所幫助,如果你有任何問題,可以在下面的評論部分提問,我會很高興回答每一個問題。

原文鏈接:https://www.smashingmagazine.com/2020/06/rest-api-react-fetch-axios/

上一篇:

比較API架構(gòu)樣式:SOAP與REST與GraphQL與RPC

下一篇:

GraphQL API手冊:如何構(gòu)建、測試、使用和記錄
#你可能也喜歡這些API文章!

我們有何不同?

API服務(wù)商零注冊

多API并行試用

數(shù)據(jù)驅(qū)動選型,提升決策效率

查看全部API→
??

熱門場景實(shí)測,選對API

#AI文本生成大模型API

對比大模型API的內(nèi)容創(chuàng)意新穎性、情感共鳴力、商業(yè)轉(zhuǎn)化潛力

25個渠道
一鍵對比試用API 限時免費(fèi)

#AI深度推理大模型API

對比大模型API的邏輯推理準(zhǔn)確性、分析深度、可視化建議合理性

10個渠道
一鍵對比試用API 限時免費(fèi)