ES6 promise 封装http请求
今天研究了一下同事封装的http请求,用的是promise。
大结构是:
const __fetch = (url, data = {}, config = {}) => { let params = Object.assign({}, data); config.headers = Object.assign({}, config.headers, { "Content-Type": "application/json", "Access-Control-Allow-Origin": "*" }); config.body = JSON.stringify(params) return Promise.race([ fetch(url, config), new Promise((resolve, reject) => { setTimeout(() => reject({ code: '504', msg: '请求超时' }), config.timeout || 20000) }) ]).then(response => { if (response.status != 200) { return Promise.reject({ code: response.status, msg: '请求失败' }) } return response.json() }, error => { if (error && error.code) { return Promise.reject(error) } }).then(response => new Promise((resolve, reject) => { if (response & response.code && response.code === '000') { resolve(response.data) } else { reject(response) } })).catch((e) => { if (!e || !e.code) return Promise.reject({ code: '999' }) if (parseInt(e.code) === 998) return Promise.reject(e) return Promise.reject({ code: e.code }) }) } } const post=(url,data={},config={})=>{ config.method='POST' return __fetch(url,data,config) }
知识点:
1.fetch()
此处可与axios做一个对比
axios需要npm install 本质上是对XHR的封装
fetch不需要npm install ES6本身就支持 直接使用(前提:浏览器支持es6语法)即可 不是对XHR的封装
但是两者都是基于Promise实现的。
axios({ method: 'post', url: '/user/12345', data: { firstName: 'Fred', lastName: 'Flintstone' } }).then(function (response) { console.log(response); }).catch(function (error) { console.log(error); });
多说一下:async/await
async 用于声明一个function是异步的,返回一个Promise对象
await可以认为是async wait的简写,表示等待一个一步方法执行完成
async-await是寄生于Promise,Generator的语法糖
try { let response = await fetch(url); //await在这里表示等待promise返回结果 再继续执行 let data = response.json(); console.log(data); } catch(e) { console.log("Oops, error", e); }
最后说 fetch
fetch(url,options)
options中第一个参数是设置请求方法(默认是get)
第二个参数是设置头部(一般是json,所以设置为application/json)第三个参数是设置包含json内容的主体
fetch('some-url',{ method:'post', headers:{'Content-Type':'application/json'}, body:JSON.stringify(content) }).then(response=>response.json()) //response.json()是返回另一个promise .then(data=>console.log(data)) .catch(error=>console.log(error))
2.Promise.race()=>多个异步任务是为了容错
Promise是一个容器,里面保存着未来某个时间点才会结束的操作。
由于fetch暂不支持超时控制,造成了流量的浪费,因此在这里使用Promise.race()对两个promise请求合并。
执行两个异步任务,一个去真实请求,一个超时报错,哪个先返回 获取哪个。
另外一个会继续执行,但是结果会被丢弃
3.job1.then(job2).then(job3).catch(handleError)
有若干个异步任务,需要先做任务1,如果成功后再做任务2,如果成功后再做任务3
任何任务失败则不再继续 并执行错误处理函数。
当promise被明确拒绝,会发生拒绝,但是如果在构造函数回调中引发的错误,会隐式拒绝,因此promise链的尾部必须有个catch接着
之所以需要用两个then,是因为fetch方法不关心ajax是否成功,只关心从服务器发送请求和接受响应。
因此第一个then是看ajax是否成功,第二个then是看具体的错误是什么,因为只有response.json.status才知道具体的错误。