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请求设置起来很简单。看看下面的代码:

fetch('http://example.com/movies.json').then(function(response) {return response.json();}).then(function(myJson) {console.log(myJson);});

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

第二个可选参数

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

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

postData('http://example.com/answer', {answer: 42}).then(data => console.log(data)) // JSON from `response.json()` call.catch(error => console.error(error))function postData(url, data) {// Default options are marked with *return fetch(url, {body: JSON.stringify(data), // must match 'Content-Type' headercache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cachedcredentials: 'same-origin', // include, same-origin, *omitheaders: {'user-agent': 'Mozilla/4.0 MDN Example','content-type': 'application/json'},method: 'POST', // *GET, POST, PUT, DELETE, etc.mode: 'cors', // no-cors, cors, *same-originredirect: 'follow', // manual, *follow, errorreferrer: 'no-referrer', // *client, no-referrer}).then(response => response.json()) // parses response to JSON
}

发送带凭据的请求

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

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

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

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

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

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

上传 JSON 数据

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

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

上传文件

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

var formData = new FormData();
var fileField = document.querySelector("input[type='file']");formData.append('username', 'abc123');
formData.append('avatar', fileField.files[0]);fetch('https://example.com/profile/avatar', {method: 'PUT',body: formData
})
.then(response => response.json())
.catch(error => console.error('Error:', error))
.then(response => console.log('Success:', response));

检测请求是否成功

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

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

自定义请求对象

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

var myHeaders = new Headers();var myInit = { method: 'GET',headers: myHeaders,mode: 'cors',cache: 'default' };var myRequest = new Request('flowers.jpg', myInit);fetch(myRequest).then(function(response) {return response.blob();
}).then(function(myBlob) {var objectURL = URL.createObjectURL(myBlob);myImage.src = objectURL;
});

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


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):

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

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

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

// 在应用中其它任何代码执行前调用一次
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) {

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

}
}

React开发中使用fetch进行异步请求相关推荐

  1. React开发中常用的工具集锦

    本文从属于笔者的React入门与最佳实践系列. 本文记录了笔者在React开发中常见的一些工具插件,如果你想寻找合适的项目生成器或者模板,请参考笔者的使用Facebook的create-react-a ...

  2. iOS网络开发中的同步、异步和请求队列

    在iOS网络编程中,我们经常会遇到线程的同步和异步问题,同时为了对异步请求更加精准丰富的控制,我们还常常在iOS中使用请求队列,下面就来谈谈iOS开发中同步.异步以及请求队列的使用方法. 1. 同步意 ...

  3. php中使用fsockopen实现异步请求

    php执行一段程序,有可能几毫秒就执行完毕,也有可能耗时较长.例如,用户下单这个事件,如果调用了些第三方服务进行发邮件.短信.推送等通知,可能导致前端一直在等待.而有的时候,我们并不关心这些耗时脚本的 ...

  4. React 开发中面临的九个重要抉择

    抉择系列:在技术开发的过程中我们会面临着各种各样的抉择,我们在不同情境下该如何选择恰当的技术,这是本系列文章想要解决的问题. 在 React 开发的过程中我们常常会遇到一些抉择,下面我将选取其中一些个 ...

  5. 微信小程序 在for循环中调用wx.request异步请求数据

    场景:渲染一个聊天列表,按消息往来时间排序. 在for循环中调用wx.request,开始在把整个for包装成一个Promise,然后发现request就是异步的,多次请求回来的数据在for循环里就出 ...

  6. iOS 开发中使用 NSURLProtocol 拦截 HTTP 请求

    这篇文章会提供一种在 Cocoa 层拦截所有 HTTP 请求的方法,其实标题已经说明了拦截 HTTP 请求需要的了解的就是 NSURLProtocol. 由于文章的内容较长,会分成两部分,这篇文章介绍 ...

  7. java web开发中会遇到的异步执行方案

    http://code.google.com/p/asyn4j/wiki/user_guide

  8. Android简单封装类似JQuery异步请求

    在android开发中经常会使用异步请求数据,通常会使用handler或者AsyncTask去做,handler 配合message 使用起来比较麻烦,AsyncTask 线程池只允许128个线程工作 ...

  9. 理解 React Native 中的 AJAX 请求

    曾经,大多数 Web 应用程序通过用户操作刷新整个网页以与 Web 服务器通信. 后来,AJAX(异步 JavaScript 和 XML)概念通过提供一种在后台与 Web 服务器通信的方式使 Web ...

最新文章

  1. 智能车竞赛技术报告 | 节能信标组组 - 大连民族大学 - 粉红靓车队
  2. laravel博客中文章删除遇到问题
  3. Turbo C 3.0安装及使用说明
  4. 使用Cygwin编译W600 sdk
  5. 【问链-Eos公开课】第三课 EOS 的新共识机制 BFT-DPoS
  6. lucky前面加a还是an_lucky的用法
  7. asp.net core 认证及简单集群
  8. Java提高篇 —— Java内部类详解
  9. R语言第十一讲 决策树与随机森林
  10. Innodb 表空间卸载、迁移、装载
  11. mysql检索整数_MyBatis从MySql DB中检索整数为Enum
  12. bzoj2456: mode
  13. Google数据集搜索神器上线,和搜索论文一样简单 | 还不去训练网络?
  14. resample函数_使用Pandas的resample函数处理时间序列数据的技巧
  15. mysql semi join_技术分享 | MySQL 子查询优化
  16. 阿里最新分享Redis全套学习笔记PDF版,图文并茂,太详细了
  17. 铁道部新客票系统设计
  18. frps实现内网穿透
  19. 播放和保存视频,图像倒置纠正到本地文件夹(含ffmpeg ,pyav多线程读取多路网络摄像头)
  20. SmartGit功能介绍

热门文章

  1. Xmanager企业版激活成功全过程
  2. FastDFS的配置、部署与API使用解读(8)FastDFS多种文件上传接口详解(转)
  3. PyCharm-professional-2018.2.2 - 破解
  4. mysql profiling 应用
  5. UVA - 1587 Box
  6. 当session会话结束时,重定向到登录页显示在iframe框内的问题
  7. 冲刺一阶段———个人总结04
  8. 一 WebService 简介
  9. HoloLens开发手记 - Unity development overview 使用Unity开发概述
  10. 三种常见的SQL分页语句