一、学习资料
1、axios:一个基于Promise 用于浏览器和 nodejs 的 HTTP 客户端
特点:
从浏览器中创建 XMLHttpRequests
从 node.js 创建 http 请求
支持 Promise API
拦截请求和响应
转换请求数据和响应数据
取消请求
自动转换 JSON 数据
客户端支持防御 XSRF
2、qs: node.js的QueryString模块
·作用是解析和格式化URL查询字符串,即对http请求所带的数据进行解析和格式化。
·只提供四个方法
1)querystring.parse(str[, separator[, eq[, options]]]) 将一个字符串反序列化为一个对象
str
<string>要解析的URL查询字符串sep
<string>用于在查询字符串中分隔键和值对的子字符串。默认为'&'
。eq
<string>。用于分隔查询字符串中的键和值的子字符串。默认为'='
。options
<对象>- o
decodeURIComponent
<function>在查询字符串中解码百分比编码字符时使用的函数。默认为querystring.unescape()
。 - o
maxKeys
<number>指定要解析的最大键数。默认为1000
。指定0
删除键盘计数限制。
- o
querystring.parse()
方法将URL查询字符串(str
)解析为键值对的集合。
例如,查询字符串'
foo=bar&abc=xyz&abc=123
'
被解析为:
2)querystring.stringfy(obj[, separator[, eq[, options]]]) 将一个对象序列化为一个字符串
obj
<Object>要序列化为URL查询字符串的对象sep
<string>用于在查询字符串中分隔键和值对的子字符串。默认为'&'
。eq
<string>。用于分隔查询字符串中的键和值的子字符串。默认为'='
。options
- o
encodeURIComponent
<function>在查询字符串中将URL不安全字符转换为百分比编码时使用的函数。默认为querystring.escape()
。
- o
该querystring.stringify()
方法obj
通过遍历对象的“自己的属性” 从给定的URL中产生一个URL查询字符串。
例子:
3)querystring.escape(str) 对传入的字符串进行编码
例子:
4)querystring.unescape(str) 对可能含有%的字符串进行解码
例子:
3、Process:node.js的一个模块,提供有关信息,控制当前node.js的进程。事实上是nodejs中的一个全局变量,因此使用的时候无需require()。
Process.env返回一个包含用户环境信息的对象。
4、axios.create()通过自定义配置新建一个axios的实例。
1)baseurl:baseurl将自动加在url前面,除非url是一个绝对url。它可以通过设置一个baseurl便于为axios实例的方法传递相对url。
2)timeout:请求超时的毫秒数,如果请求花费超过了timeout的时间,请求将被中断。
3)header:被发送的自定义请求头
·Content-Type代表发送端发送的实体数据的数据类型。
application/x-www-form-urlencoded是最常见的post提交数据的方式,提交的数据按照键值对key1=val1&key2=val2的方式进行编码
·Accept代表发送端(客户端)希望接受的数据类型。
application/json客户端接受服务端json格式的数据。
· If-Modified-Since
Last-Modified 是由服务器往客户端发送的 HTTP 头,而 If-Modified-Since 则是由客户端往服务器发送的头。再次请求本地存在的 cache 页面时,客户端会通过 If-Modified-Since 将先前服务器端发过来的 Last-Modified 最后修改时间戳发送回去,这是为了让服务器端进行验证,通过这个时间戳判断客户端的页面是否是最新的,如果不是最新的,则返回新的内容,如果是最新的,则 返回 304 告诉客户端其本地 cache 的页面是最新的,于是客户端就可以直接从本地加载页面了,这样在网络上传输的数据就会大大减少,同时也减轻了服务器的负担。
5、只读函数get:
axios实例的get方法:axios.get(url[ ,config ])
·url<string> 用于请求的服务器url
·config <obj> 创建请求时的配置选项,可在https://www.kancloud.cn/yunye/axios/234845详细查看
函数里设置创建请求的配置选项,包括params(即将与请求一起发送的url参数)和请求超时的时间。
配置过程:请求时发送的数据不为空,对象params的属性params(params是即将与请求一起发送的url参数)就等于data,timeout不为0,params的属性timeout就等于timeout。
axios的get请求返回的也是一个promise对象,跟踪对象只要后面加一个catch方法就好了。
6、 只读函数post:
axios实例的post方法:axios.post(url[ ,data[ ,config ]])
·url<string> 用于请求的服务器url
·config <obj> 创建请求时的配置选项,可在https://www.kancloud.cn/yunye/axios/234845详细查看
函数里设置post发送的数据和创建请求的配置选项,包括请求超时的时间。
axios的post请求返回的也是一个promise对象,跟踪对象只要后面加一个catch方法。
7、 promise的作用与回调方法(callback)一样,都是在某种情况下执行设定好的方法。但promise的多重链式调用能使代码更整洁,避免出现“回调地狱”(回调嵌套太多层)。在es6中,promise成为了原生对象可以直接使用。
Ajax请求的传统写法:
改为promise写法:
很显然,promise的写法把异步调用中使用回调函数的场景改为了.then()、.catch()等函数链式调用的方式,基于promise可以把复杂的异步调用方式进行模块化。
Promise的原理分析:
Promise对象共有三个状态,分别是:
·pending(进行中)
·resolved(已完成,又称为fullfilled)
·rejected(已失败)
由异步操作的结果决定当前是什么状态。状态的改变只有两种可能:
·从pending变为fullfilled
·从pending变为rejected
只要这两种情况发生,状态就不会再改变了,因此状态是不能逆向改变的。
构建promise:
Promise的构造函数接受一个函数作为参数,该函数的两个参数分别为resolve和reject两个函数。
·Resolve函数将promise对象的状态由pending变为resolved,异步操作成功时调用,并将异步操作的结果,作为参数传递出去。
·reject函数将状态由pending变为rejected,异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
Promise的实例方法:
Promise对象拥有两个实例方法then()和catch()。
·then()方法接受两个函数作为参数,第一个是状态变为resolved时调用,第二个则是状态变为rejected是调用,第二个函数是可选的。
Promise实例生成以后,可以用then
方法指定resolved
状态和rejected
状态的回调函数,即成功和失败的回调函数。
promise
构造函数中通常都是异步的,所以then
方法往往都先于resolve
和reject
方法执行。这两个函数作为成功和失败的回调函数,都接受promise对象传出的值作为参数。
then()方法将返回一个新的promise。
因此then可以链式调用,在新的对象上添加失败或成功的回调。
·catch()方法的作用是捕获promise的错误。
与then()方法的rejected回调作业几乎一致。
我们知道,如果 Promise 状态已经变成resolved
,再抛出错误是无效的。
上面代码中,Promise 在resolve
语句后面,再抛出错误,不会被捕获,等于没有抛出。因为 Promise 的状态一旦改变,就永久保持该状态,不会再变了。
由于promise对象的错误会一直向后传递,直到被捕获,即错误总会被下一个catch
所捕获。then
方法指定的回调函数,若抛出错误,也会被下一个catch
捕获。catch
中也能抛错,则需要后面的catch
来捕获。
一般来说,不要在then
方法里面定义 Reject 状态的回调函数(即then
的第二个参数),总是使用catch
方法。
这样就能够在下一个catch()中统一处理这些错误。同时catch()也能够捕获then()中抛出的错误,所以建议不使用then()的rejected回调,而是统一使用catch()来处理错误。
跟传统的try/catch
代码块不同的是,如果没有使用catch
方法指定错误处理的回调函数,Promise 对象抛出的错误不会传递到外层代码,即不会有任何反应。Promise 内部的错误不会影响到 Promise 外部的代码。
二、总结
Ajax.js的流程(过程):
1、创建axios的实例
const instance = axios.create({ baseURL: baseUrl, timeout: 20000, headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Accept': 'application/json', 'If-Modified-Since': '0' } });
2、封装axios实例的get和post方法:
若执行只读函数get()或post():
1)分别发送get请求和post请求
2)用catch捕获错误和处理错误,
3)返回一个新的promise实例。
const get = (url, data, timeout) => { let params; if (data) { params = { params: data }; } if (timeout) { params.timeout = timeout; } return instance .get(url, params) .catch(handleError); }; const post = (url, data, timeout) => { data = qs.stringify(data); const config = { timeout }; return instance .post(url, data, config) .catch(handleError); };
3、封装get和post的接口:
若执行getAPI()或者postAPI(),会返回一个promise实例,生成该promise实例的构造函数做了除了返回一个新的promise实例以外的以下几件事情:
1)分别执行了封装好的get()方法和post()方法
2)利用promise的then()方法指定了get()或者post()成功以后调用的回调函数resolve(response.data)
const getApi = (url, data, timeout) => { return new Promise((resolve, reject) => { get(url, data, timeout) .then(response => { resolve(response.data); }); }); }; const postApi = (url, data, timeout) => { return new Promise((resolve, reject) => { post(url, data, timeout) .then(response => { resolve(response.data); }); }); };
三、参考文档
ECMAScript 6 入门
http://es6.ruanyifeng.com/#docs/promise#%E5%9F%BA%E6%9C%AC%E7%94%A8%E6%B3%95
初探promise
https://segmentfault.com/a/1190000007032448
Axios 中文说明
https://www.kancloud.cn/yunye/axios/234845
Node.js v9.40文档
https://nodejs.org/api/querystring.html