【系列化】reactJS项目构建6--fetch基础
发布在reactJS2017年12月6日view:145
在文章任何区域双击击即可给文章添加【评注】!浮到评注点上可以查看详情。

背景

在 jQuery 开发时代,jQuery 已经为我们封装了非常优雅的 ajax 函数,并且针对各个浏览器都做了很好的兼容,非常棒。但是如果你用 React vue 或者 angular 去开发 webapp 时候,你还会再为了一个 ajax 去集成 jQuery 吗?这是一个问题。

另外一个问题,JavaScript 中的 ajax 很早之前就有一个诟病————复杂业务下的 callback 嵌套的问题。如果你对此了解不深刻,建议你去查一下“JavaScript promise”相关的资料。

promise 正是 js 中解决这一问题的钥匙,并且作为标准在 ES6 中发布,接下来要介绍的 fetch 就用到了最新的 promise

fetch就是一种可代替 ajax 获取/提交数据的技术,有些高级浏览器已经可以window.fetch使用了。相比于使用 jQuery.ajax 它轻量(只做这一件事),而且它原生支持 promise ,更加符合现在编程习惯。


安装

根据文档提示,用 npm 安装的话,执行 npm install whatwg-fetch --save 即可安装。为了兼容老版本浏览器,还需要安装 npm install es6-promise --save 。安装完成之后,注意看一下 package.json 中的变化。


Get基本使用

首先需要引入依赖的插件

import 'whatwg-fetch'
import 'es6-promise'

然后我们看下Get请求在fetch下如何使用 :

var result = fetch('/api/1', {
    credentials: 'include',
    headers: {
        'Accept': 'application/json, text/plain, */*'
    }
});

以上代码的配置中,credentials: 'include' 表示跨域请求是可以带cookie(fetch 跨域请求时默认不会带 cookie,需要时得手动指定。这和 XHR 的 withCredentials 一样),headers 可以设置 http 请求的头部信息。

fetch 方法请求数据,返回的是一个 Promise 对象,接下来我们就可以这样用了——完全使用Promise的语法结构。

result.then(res => {
    return res.text()
}).then(text => {
    console.log(text)
})

或者这样:

result.then(res => {
    return res.json()
}).then(json => {
    console.log(json)
})

*以上两个用法中,只有 res.text()res.json() 这里不一样————这两个方法就是将返回的 Response 数据转换成字符串或者JSON格式,这也是 js 中常用的两种格式。


Post基本使用

同样,也需要引入依赖插件

import 'whatwg-fetch'
import 'es6-promise'

然后用 fetch 发起一个 post 请求(有 method: 'POST' ),第一个参数是 url,第二个参数是配置信息。注意下面配置信息中的 headersbody 的格式。

var result = fetch('/api/post', {
    method: 'POST',
    credentials: 'include',
    headers: {
        'Accept': 'application/json, text/plain, */*',
        'Content-Type': 'application/x-www-form-urlencoded'
    },
    // 注意 post 时候参数的形式
    body: "a=100&b=200"
});

fetch 提交数据之后,返回的结果也是一个 Promise 对象,跟 get 方法一样,因此处理方式也一样,上面刚描述了,因此不再赘述。


抽象 Get 和 Post

如果每次获取数据,都向上面一样写好多代码,就太冗余了,我们这里将 get 和 post 两个方法单独抽象出来。代码如下:

Get抽象
import 'whatwg-fetch'
import 'es6-promise'

export function get(url) {
  var result = fetch(url, {
      credentials: 'include',
      headers: {
          'Accept': 'application/json, text/plain, */*'
      }
  });

  return result;
}
Post抽象
import 'whatwg-fetch'
import 'es6-promise'

// 将对象拼接成 key1=val1&key2=val2&key3=val3 的字符串形式
function obj2params(obj) {
    var result = '';
    var item;
    for (item in obj) {
        result += '&' + item + '=' + encodeURIComponent(obj[item]);
    }

    if (result) {
        result = result.slice(1);
    }

    return result;
}

// 发送 post 请求
export function post(url, paramsObj) {
    var result = fetch(url, {
        method: 'POST',
        credentials: 'include',
        headers: {
            'Accept': 'application/json, text/plain, */*',
            'Content-Type': 'application/x-www-form-urlencoded'
        },
        body: obj2params(paramsObj)
    });

    return result;
}

数据Mock

在目前互联网行业 web 产品开发中,前后端大部分都是分离开发的,前端开发过程中无法实时得到后端的数据。这种情况下,一般会使用三种方式:

  • 模拟静态数据:即按照既定的数据格式,自己提供一些静态的JSON数据,用相关工具(如fis3)做接口来获取这些数据。该形式使用不比较简单的、只用 get 方法的场景,该项目不适用。

  • 模拟动态接口:即自己用一个 web 框架,按照既定的接口和数据结构的要求,自己模拟后端接口的功能,让前端项目能顺利跑起来。该方式适用于新开发的项目,后端和前端同时开发,适用于该教程的项目。

  • 转发线上接口:项目开发中,所有的接口直接用代理获取线上的数据,post 的数据也都直接提交到线上。该方式适用于成熟项目中,而该项目是新开发的,没有线上接口,不适用。

安装

这里我们使用目前比较流行的 koa 来做后端接口的模拟。因此要先安装 koa 极其相关的插件。

执行 npm install koa koa-body koa-router --save-dev ,注意这里使用 --save-dev ,意思是我们只在开发过程中使用 koa ,项目发布之后 koa 就没用了。

因为发布之后的项目,使用的就是后端工程师开发的线上的接口,而不是我们基于 koa 写的接口。

注意,想学习koa可以去官网或者找相关教程。

模拟接口

我们将模拟接口的代码都写在 ./mock 目录下,接口文件是 ./mock/server.js(目前只有这一个文件,真正开发项目时,应该会分不同模块)。

然后在 ./package.json 中增加如下代码,然后执行 npm run mock 即可启动模拟的接口服务。

"scripts": {
    "mock": "node --harmony ./mock/server.js"
  }

启动之后,随便找一个 get 的接口,访问以下,例如 http://localhost:3000/api/1

使用 webpack-dev-server 的代理

到这里你可能会有一个疑问——koa 接口的端口是 3000,而我们项目的接口是 8080,这样不就跨域了吗?

如果默认情况下,肯定是跨域了。此时就需要 webpack-dev-server 做一个代理的转发。配置代码在 ./webpack.config.js 中, 代码如下:

devServer: {
    proxy: {
      // 凡是 `/api` 开头的 http 请求,都会被代理到 localhost:3000 上,由 koa 提供 mock 数据。
      // koa 代码在 ./mock 目录中,启动命令为 npm run mock
      '/api': {
        target: 'http://localhost:3000',
        secure: false
      }
    },
    // ... 省略若干代码 ...
}
评论
发表评论
暂无评论
WRITTEN BY
娜娜娜娜
本人已懒到爆……
TA的新浪微博
PUBLISHED IN
reactJS

我竟然还会这个~

我的收藏