最近想用全js系统的写一遍先后端学习一下,就建立了一套TODOList项目练手。当前仅写完了后端demo,前端正在使用vue。而且准备之后再用react和flutter再写一遍。
此项目
后端demo
在写练手项目的时候使用了Framework7
这个移动端ui框架,由于这个框架的动画写的很厉害因此选择了它。可是在使用过程当中,发现这个框架自带的ajax请求库特别简单,因而参照axios
手动封装了一下,使其支持promise和拦截器。javascript
废话很少说,上代码comover.js
前端
import { Request as F7Request } from "framework7"; // 将原始请求对象封装成Promise对象 function adapter(config) { return new Promise(function(resolve, reject) { F7Request({ url: `${config.baseUrl}${config.url}`, method: config.method, headers: config.headers, data: config.data, success(data, status, xhr) { resolve({ data: JSON.parse(data), status: status, config: config, xhr: xhr }); }, error(xhr, status) { let error = new Error( `Request failed with status code ${status}` ); error.xhr = xhr; reject(error); } }); }); } // 发送请求 function dispatchRequest(config) { return adapter(config).then( function onAdapterResolution(response) { return response; }, function onAdapterRejection(reason) { return Promise.reject(reason); } ); } export default class Comeover { interceptors = {}; requestHandlers = []; responseHandlers = []; config = {}; constructor(config = ({ baseUrl = "" } = {})) { const self = this; this.config = { ...config }; this.interceptors = { request: { use(fulfilled, rejected) { self.requestHandlers.push({ fulfilled, rejected }); } }, response: { use(fulfilled, rejected) { self.responseHandlers.push({ fulfilled, rejected }); } } }; // ES6中class内方法运行时绑定上下文 this.request = this.request.bind(this); } request(config) { // 合并默认config和发送请求时的config let inconfig = { ...this.config, ...config }; // 建立Promise链 let chain = [dispatchRequest, undefined]; // 建立初始Promise链中传递的promise对象 let promise = Promise.resolve(inconfig); // 将拦截器注入Promise链 this.requestHandlers.forEach(interceptor => { chain.unshift(interceptor.fulfilled, interceptor.rejected); }); this.responseHandlers.forEach(interceptor => { chain.push(interceptor.fulfilled, interceptor.rejected); }); // 运行Promise链 while (chain.length) { promise = promise.then(chain.shift(), chain.shift()); } // 返回最终的promise对象 return promise; } }
这个例子就是在全部请求先后使用nprogress伪装显示一下请求进度vue
import Comeover from "./comeover"; import Np from "nprogress"; const baseUrl = process.env.NODE_ENV === "development" ? "" : /* 上线地址 */ ""; const comeover = new Comeover({ baseUrl }); comeover.interceptors.request.use( config => { Np.start(); return config; }, error => { Np.done(); return Promise.reject(error); } ); comeover.interceptors.response.use( response => { Np.done(); return response; }, error => { Np.done(); return Promise.reject(error); } ); export { request };
comeover.request({ url: "/api/login", method: "post", data: { email: this.email, password: this.password } }) .then(({ data }) => { this.$store.commit("login", { token: data.message }); router.back(); }) .catch(err => { app.dialog.alert("用户名或密码错误", "登录失败"); });
还能够参照axios
继续封装单独的get、post等等的方法,这个demo就不写了。
Promise链是个数组,而后把请求拦截器放到真正请求的前面,响应后的拦截器放在真请求的后面。而后以resolve
在前,reject
在后的顺序,成对循环注入到promise.then
中。而真正请求的resove
和reject
是写在dispatchRequest
里的,因此dispatchRequest
这里没有reject,要加一个undefined
。
ES6的实例化方法单独使用的时候this指向会有问题,须要单独处理java