React开发中使用fetch进行异步请求

前端之家收集整理的这篇文章主要介绍了React开发中使用fetch进行异步请求前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

React开发中使用fetch进行异步请求

最新的Web API接口中提供了一个全局fetch方法,从而以一种更为简单、合理的方式来支持跨网络异步获取资源。

这种功能以前是使用 XMLHttpRequest实现的。Fetch提供了一个更好的替代方法,可以很容易地被其他技术使用,例如 Service Workers。Fetch还提供了单个逻辑位置来定义其他HTTP相关概念,例如CORS和HTTP的扩展。

请注意,fetch规范与jQuery.ajax()主要有两种方式的不同:

  • 当接收到一个代表错误的 HTTP 状态码时,从 fetch()返回的 Promise 不会被标记为 reject, 即使该 HTTP 响应的状态码是 404 或 500。相反,它会将 Promise 状态标记为 resolve (但是会将 resolve 的返回值的 ok 属性设置为 false ),仅当网络故障时或请求被阻止时,才会标记为 reject。
  • 默认情况下,fetch 不会从服务端发送或接收任何 cookies,如果站点依赖于用户 session,则会导致未经认证的请求(要发送 cookies,必须设置 credentials 选项)。

基本的fetch请求举例

一个基本的 fetch请求设置起来很简单。看看下面的代码

  1. fetch('http://example.com/movies.json')
  2. .then(function(response) {
  3. return response.json();
  4. })
  5. .then(function(myJson) {
  6. console.log(myJson);
  7. });

这里我们通过网络获取一个JSON文件并将其打印到控制台。最简单的用法是只提供一个参数用来指明想fetch()到的资源路径,然后返回一个包含响应结果的promise(一个 Response 对象)。

第二个可选参数

fetch() 接受第二个可选参数,一个可以控制不同配置的 init 对象:

参考 fetch(),查看所有可选的配置和更多描述。

  1. postData('http://example.com/answer',{answer: 42})
  2. .then(data => console.log(data)) // JSON from `response.json()` call
  3. .catch(error => console.error(error))
  4.  
  5. function postData(url,data) {
  6. // Default options are marked with *
  7. return fetch(url,{
  8. body: JSON.stringify(data),// must match 'Content-Type' header
  9. cache: 'no-cache',// *default,no-cache,reload,force-cache,only-if-cached
  10. credentials: 'same-origin',// include,same-origin,*omit
  11. headers: {
  12. 'user-agent': 'Mozilla/4.0 MDN Example','content-type': 'application/json'
  13. },method: 'POST',// *GET,POST,PUT,DELETE,etc.
  14. mode: 'cors',// no-cors,cors,*same-origin
  15. redirect: 'follow',// manual,*follow,error
  16. referrer: 'no-referrer',// *client,no-referrer
  17. })
  18. .then(response => response.json()) // parses response to JSON
  19. }

发送带凭据的请求

为了让浏览器发送包含凭据的请求(即使是跨域源),要将credentials: 'include'添加到传递给 fetch()方法的init对象。

  1. fetch('https://example.com',{
  2. credentials: 'include'
  3. })

如果你只想在请求URL与调用脚本位于同一起源处时发送凭据,请添加credentials: 'same-origin'。

  1. // The calling script is on the origin 'https://example.com'
  2. fetch('https://example.com',{
  3. credentials: 'same-origin'
  4. })

要改为确保浏览器不在请求中包含凭据,请使用credentials: 'omit'。

  1. fetch('https://example.com',{
  2. credentials: 'omit'
  3. })

上传 JSON 数据

下面的示例片断展示了使用fetch()方法以POST方式发送 JSON编码的数据:

  1. var url = 'https://example.com/profile';
  2. var data = {username: 'example'};
  3.  
  4. fetch(url,{
  5. method: 'POST',// or 'PUT'
  6. body: JSON.stringify(data),// data can be `string` or {object}!
  7. headers: new Headers({
  8. 'Content-Type': 'application/json'
  9. })
  10. }).then(res => res.json())
  11. .catch(error => console.error('Error:',error))
  12. .then(response => console.log('Success:',response));

上传文件

在最新浏览器API编程中,你可以使用一个HTML <input type="file" /> 输入元素,并结合FormData() 函数和fetch()函数实现上传文件

  1. var formData = new FormData();
  2. var fileField = document.querySelector("input[type='file']");
  3.  
  4. formData.append('username','abc123');
  5. formData.append('avatar',fileField.files[0]);
  6.  
  7. fetch('https://example.com/profile/avatar',{
  8. method: 'PUT',body: formData
  9. })
  10. .then(response => response.json())
  11. .catch(error => console.error('Error:',response));

检测请求是否成功

如果遇到网络故障,fetch() (其实是一个promise对象)将会Reject,带上一个 TypeError 对象。虽然这个情况经常是遇到了权限问题或类似问题——比如 404 不是一个网络故障。想要精确的判断 fetch() 是否成功,需要包含 promise解析的情况,此时再判断 Response.ok 是不是为 true。类似以下代码

  1. fetch('flowers.jpg').then(function(response) {
  2. if(response.ok) {
  3. return response.blob();
  4. }
  5. throw new Error('Network response was not ok.');
  6. }).then(function(myBlob) {
  7. var objectURL = URL.createObjectURL(myBlob);
  8. myImage.src = objectURL;
  9. }).catch(function(error) {
  10. console.log('There has been a problem with your fetch operation: ',error.message);
  11. });

自定义请求对象

除了传给 fetch() 一个资源的地址,你还可以通过使用 Request() 构造函数来创建一个 request 对象,然后再作为参数传给 fetch():

  1. var myHeaders = new Headers();
  2.  
  3. var myInit = { method: 'GET',headers: myHeaders,mode: 'cors',cache: 'default' };
  4.  
  5. var myRequest = new Request('flowers.jpg',myInit);
  6.  
  7. fetch(myRequest).then(function(response) {
  8. return response.blob();
  9. }).then(function(myBlob) {
  10. var objectURL = URL.createObjectURL(myBlob);
  11. myImage.src = objectURL;
  12. });

Request() 和 fetch() 接受同样的参数。你甚至可以传入一个已存在的 request 对象来创造一个拷贝:

  1. var anotherRequest = new Request(myRequest,myInit);

这个很有用,因为 request 和 response bodies 只能被使用一次(译者注:这里的意思是因为设计成了 stream 的方式,所以它们只能被读取一次)。创建一个拷贝就可以再次使用 request/response 了,当然也可以使用不同的 init 参数。

React开发中使用fetch

要在不支持的浏览器中使用Fetch,可以使用Fetch Polypill(https://github.com/github/fetch)。

上面示例中使用了 fetch API。它是替代 XMLHttpRequest 用来发送网络请求的非常新的 API。由于目前大多数浏览器原生还不支持它,React开发中建议你使用 cross_fetch 库(https://github.com/lquixada/cross-fetch):

  1. // 每次使用 `fetch` 前都这样调用一下
  2. import fetch from 'cross_fetch'

在底层,它在浏览器端使用 whatwg-fetch polyfill,在服务器端使用 node-fetch,所以如果当你把应用改成 同构 时,并不需要改变 API 请求。

注意,fetch polyfill 假设你已经使用了 Promise 的 polyfill。确保你使用 Promise polyfill 的一个最简单的办法是在所有应用代码前启用 Babel 的 ES6 polyfill:

  1. // 在应用中其它任何代码执行前调用一次
  2. import 'babel-polyfill'

一个相对完整的使用fetch的例子

import fetch from 'cross-fetch'

export const REQUEST_POSTS = 'REQUEST_POSTS'
function requestPosts(subreddit) {
return {
type: REQUEST_POSTS,
subreddit
}
}

export const RECEIVE_POSTS = 'RECEIVE_POSTS'
function receivePosts(subreddit,json) {
return {
type: RECEIVE_POSTS,
subreddit,
posts: json.data.children.map(child => child.data),
receivedAt: Date.now()
}
}

export const INVALIDATE_SUBREDDIT = ‘INVALIDATE_SUBREDDIT’
export function invalidateSubreddit(subreddit) {
return {
type: INVALIDATE_SUBREDDIT,
subreddit
}
}

// 来看一下我们写的第一个 thunk action 创建函数
// 虽然内部操作不同,你可以像其它 action 创建函数 一样使用它:
// store.dispatch(fetchPosts('reactjs'))

export function fetchPosts(subreddit) {

// Thunk middleware 知道如何处理函数
// 这里把 dispatch 方法通过参数的形式传给函数
// 以此来让它自己也能 dispatch action。

return function (dispatch) {

  1. // 首次 dispatch:更新应用的 state 来通知
  2. // API 请求发起了。
  3.  
  4. dispatch(requestPosts(subreddit))
  5.  
  6. // thunk middleware 调用函数可以有返回值,
  7. // 它会被当作 dispatch 方法的返回值传递。
  8.  
  9. // 这个案例中,我们返回一个等待处理的 promise。
  10. // 这并不是 redux middleware 所必须的,但这对于我们而言很方便。
  11.  
  12. return fetch(`http://www.subreddit.com/r/${subreddit}.json`)
  13. .then(
  14. response => response.json(),// 不要使用 catch,因为会捕获
  15. // 在 dispatch 和渲染中出现的任何错误
  16. // 导致 'Unexpected batch number' 错误
  17. // https://github.com/facebook/react/issues/6895
  18. error => console.log('An error occurred.',error)
  19. )
  20. .then(json =>
  21. // 可以多次 dispatch!
  22. // 这里,使用 API 请求结果来更新应用的 state。
  23.  
  24. dispatch(receivePosts(subreddit,json))
  25. )

}}

猜你在找的React相关文章