一、axios
1.1 axios是什么
axios是基于promise封装的ajax库,用于客户端发送ajax请求;
1.2 安装axios库
npm install axios --save 或者 yarn add axios --save
1.3 axios常用的方法:
1.3.1 get请求
- axios.get(url, config)
 - 返回promise对象
 
axios.get('/api/get_aside', {params: {aside_id: 1}}).then(({data}) => bindHTML(data));
1.3.2 post请求
- axios.post(url, data)
 - 返回promise对象,可以使用.then,then回调的形参res:
- res 是一个经过axios封装过的对象,其中包含了http的响应状态,响应状态码等信息;
 - 对象中的data属性值才是我们请求来的数据
 - console.log(res);
 - console.log(res.data);
 
 
axios.post('/api/get_aside', {aside_id: 1, name: 'xyz'}).then(function (res) {// res 是一个经过axios封装过的对象,其中包含了http的响应状态,响应状态码等信息;// 对象中的data属性值才是我们请求来的数据// console.log(res);// console.log(res.data);bindHTML(res.data);});
1.3.3 并发多个请求,并且要等所有请求结束之后再做处理
- axios.all([axios请求1, axios请求2, ….])
 - 仍然返回then,但是then方法中要传入 axios.spread(callback)
 
示例:
function getUser(uid) {return axios.get(`/api/get_user?u_id=${uid}`)}function getAside(aid) {return axios.get(`/api/get_aside?a_id=${aid}`)}axios.all([getUser(1), getAside(1)]).then(axios.spread((user, aside) => {console.log(user);console.log(aside);}))
二、ajax接口
返回静态资源文件如html、css、js、图片的服务称为静态资源服务;而ajax接口一般根据客户端的请求返回具体的内容;
2.1 Node静态资源服务器
let http = require('http');let fs = require('fs');let url = require('url');let mime = require('mime');let server = http.createServer((req, res) => {let {method} = req;let urlObj = url.parse(req.url, true);let {pathname} = urlObj;let filePath = '';let contentType = '';if (pathname === '/') {filePath = __dirname + '/index.html';contentType = 'text/html';} else {filePath = __dirname + pathname;contentType = mime.getType(pathname);}fs.readFile(filePath, (err, data) => {if (err) {res.statusCode = 404;res.end(`${pathname} You are looking for is not found`);} else {res.setHeader('Content-Type', contentType);res.end(data);}})});server.listen(8000, () => console.log('port 8000 is on'));
2.2 增加ajax接口
- 如何区分ajax接口还是静态资源服务请求?
静态资源文件请求一般包含文件的扩展名,特殊的有 / ,所以如果pathname有扩展名或者是 / 就是静态资源服务,否则就是接口; - 所有的ajax接口返回json,设置内容类型为 application/json;
 - 设置返回json的编码为 charset=UTF-8; 如果不设置返回的json会乱码;
 
let http = require('http');let fs = require('fs');let url = require('url');let mime = require('mime');let server = http.createServer((req, res) => {let {method} = req;let urlObj = url.parse(req.url, true);let {pathname} = urlObj;let filePath = '';let contentType = '';// 1. 静态资源服务if (pathname === '/' || /(\.\w+)$/.test(pathname)) {if (pathname === '/') {filePath = __dirname + '/index.html';contentType = 'text/html';} else {filePath = __dirname + pathname;contentType = mime.getType(pathname);}fs.readFile(filePath, (err, data) => {if (err) {res.statusCode = 404;res.end(`${pathname} You are looking for is not found`);} else {res.setHeader('Content-Type', contentType);res.end(data);}})} else {// ajax 接口res.setHeader('Content-Type', 'application/json;charset=UTF-8;');if (pathname === '/api/get_aside') {// 使用data和end事件获取post请求的数据if (method.toUpperCase === 'POST') {var postStr = '';req.on('data', (data) => postStr += data);req.on('end', () => {let obj = JSON.parse(postStr);fs.readFile(__dirname + '/aside.json', (err, data) => {if (err) {res.statusCode = 404;res.end(`${pathname} You are looking for is not found`);} else {res.setHeader('Content-Type', 'application/json;charset=UTF-8;');res.end(data);}});});} else {fs.readFile(__dirname + '/aside.json', (err, data) => {if (err) {res.statusCode = 404;res.end(`${pathname} You are looking for is not found`);} else {res.end(data);}});}}// 获取用户的信息if (pathname === '/api/get_user') {let urlObj = url.parse(req.url, true);let {u_id} = urlObj.query;fs.readFile(__dirname + '/user.json', 'utf8', function (err, data) {let dataArr = JSON.parse(data);let user = dataArr.find(item => +item.id === +u_id);if (user) {res.end(JSON.stringify({code: 0,data: {token: 'adsflkds1fldslafk'},msg: 'ok'}))} else {res.end(JSON.stringify({code: -1,data: {},msg: '用户不存在'}))}})}}});server.listen(8000, () => console.log('port 8000 is on'));
三、PromiseA+
实现一个Promise
class MyPromise {constructor (executor) {// this 是当前类的实例// 当resolve执行时,会把当前实例上成功的事件池中的所有函数挨个执行// 给实例添加两个事件池,一个是装成功的事件函数,一个装失败的事件函数// 初始化一个状态 pending// 初始化一个值valuethis.state = 'pending';this.fulfilledEvent = [];this.rejectedEvent = [];this.value = undefined;let resolve = (result) => {// 循环事件池中的函数,让其按个执行// 修改状态,一旦状态发生变更就不能再修改状态if (this.state !== 'pending') return;this.state = 'fulfilled';this.value = result;setTimeout(() => {this.fulfilledEvent.forEach(fulfillCb => {if (typeof fulfillCb === 'function') fulfillCb(this.value);}, 0)})};// 当reject时,把实例上保存失败的事件池中的函数都执行了let reject = (reason) => {if (this.state !== 'pending') return;this.state = 'rejected';this.value = reason;let timer = setTimeout(() => {clearTimeout(timer); // 这里为啥要清除timer???this.rejectedEvent.forEach(rejectCb => {if (typeof rejectCb === 'function') rejectCb(this.value);})})};// 处理Promise的异常try {executor(resolve, reject);} catch (e) {reject(e)}}then (resolveFn, rejectFn) {// 如果then方法中没有传递resolveFn或者rejectFn,要自动补全if (!resolveFn) {resolveFn = result => result;}if (!rejectFn) {rejectFn = reason => {throw new Error(reason)}}return new MyPromise((resolve, reject) => {// 不是直接把函数放进去,因为需要判断当前函数是否返回一个Promise实例this.fulfilledEvent.push((result) => {try {let x = resolveFn(result);x instanceof MyPromise? x.then(resolve, reject): resolve(result);} catch (e) {reject(e)}});this.rejectedEvent.push(reason => {try {let x = rejectFn(reason);x instanceof MyPromise? x.then(resolve, reject): resolve(x); // 如果不是Promise实例,直接执行下一个then中的resolve} catch (e) {reject(e);}})})}}
使用
new MyPromise((resolve, reject) => {console.log(1);reject('abc');}).then(function (res) {console.log(2);}, function (err) {console.log(3)}).then((res) => {console.log(4)}, function () {console.log(5)});console.log(6);
【发上等愿,结中等缘,享下等福,择高处立,寻平处住,向宽处行】
