珠峰培训,专注前端

一、axios

1.1 axios是什么

axios是基于promise封装的ajax库,用于客户端发送ajax请求;

1.2 安装axios库

  1. npm install axios --save 或者 yarn add axios --save

1.3 axios常用的方法:

1.3.1 get请求

  • axios.get(url, config)
  • 返回promise对象
  1. axios.get('/api/get_aside', {
  2. params: {
  3. aside_id: 1
  4. }
  5. }).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);
  1. axios.post('/api/get_aside', {aside_id: 1, name: 'xyz'}).then(function (res) {
  2. // res 是一个经过axios封装过的对象,其中包含了http的响应状态,响应状态码等信息;
  3. // 对象中的data属性值才是我们请求来的数据
  4. // console.log(res);
  5. // console.log(res.data);
  6. bindHTML(res.data);
  7. });

1.3.3 并发多个请求,并且要等所有请求结束之后再做处理

  • axios.all([axios请求1, axios请求2, ….])
  • 仍然返回then,但是then方法中要传入 axios.spread(callback)

示例:

  1. function getUser(uid) {
  2. return axios.get(`/api/get_user?u_id=${uid}`)
  3. }
  4. function getAside(aid) {
  5. return axios.get(`/api/get_aside?a_id=${aid}`)
  6. }
  7. axios.all([getUser(1), getAside(1)]).then(axios.spread((user, aside) => {
  8. console.log(user);
  9. console.log(aside);
  10. }))

二、ajax接口

返回静态资源文件如html、css、js、图片的服务称为静态资源服务;而ajax接口一般根据客户端的请求返回具体的内容;

2.1 Node静态资源服务器

  1. let http = require('http');
  2. let fs = require('fs');
  3. let url = require('url');
  4. let mime = require('mime');
  5. let server = http.createServer((req, res) => {
  6. let {method} = req;
  7. let urlObj = url.parse(req.url, true);
  8. let {pathname} = urlObj;
  9. let filePath = '';
  10. let contentType = '';
  11. if (pathname === '/') {
  12. filePath = __dirname + '/index.html';
  13. contentType = 'text/html';
  14. } else {
  15. filePath = __dirname + pathname;
  16. contentType = mime.getType(pathname);
  17. }
  18. fs.readFile(filePath, (err, data) => {
  19. if (err) {
  20. res.statusCode = 404;
  21. res.end(`${pathname} You are looking for is not found`);
  22. } else {
  23. res.setHeader('Content-Type', contentType);
  24. res.end(data);
  25. }
  26. })
  27. });
  28. server.listen(8000, () => console.log('port 8000 is on'));

2.2 增加ajax接口

  • 如何区分ajax接口还是静态资源服务请求?
    静态资源文件请求一般包含文件的扩展名,特殊的有 / ,所以如果pathname有扩展名或者是 / 就是静态资源服务,否则就是接口;
  • 所有的ajax接口返回json,设置内容类型为 application/json;
  • 设置返回json的编码为 charset=UTF-8; 如果不设置返回的json会乱码;
  1. let http = require('http');
  2. let fs = require('fs');
  3. let url = require('url');
  4. let mime = require('mime');
  5. let server = http.createServer((req, res) => {
  6. let {method} = req;
  7. let urlObj = url.parse(req.url, true);
  8. let {pathname} = urlObj;
  9. let filePath = '';
  10. let contentType = '';
  11. // 1. 静态资源服务
  12. if (pathname === '/' || /(\.\w+)$/.test(pathname)) {
  13. if (pathname === '/') {
  14. filePath = __dirname + '/index.html';
  15. contentType = 'text/html';
  16. } else {
  17. filePath = __dirname + pathname;
  18. contentType = mime.getType(pathname);
  19. }
  20. fs.readFile(filePath, (err, data) => {
  21. if (err) {
  22. res.statusCode = 404;
  23. res.end(`${pathname} You are looking for is not found`);
  24. } else {
  25. res.setHeader('Content-Type', contentType);
  26. res.end(data);
  27. }
  28. })
  29. } else {
  30. // ajax 接口
  31. res.setHeader('Content-Type', 'application/json;charset=UTF-8;');
  32. if (pathname === '/api/get_aside') {
  33. // 使用data和end事件获取post请求的数据
  34. if (method.toUpperCase === 'POST') {
  35. var postStr = '';
  36. req.on('data', (data) => postStr += data);
  37. req.on('end', () => {
  38. let obj = JSON.parse(postStr);
  39. fs.readFile(__dirname + '/aside.json', (err, data) => {
  40. if (err) {
  41. res.statusCode = 404;
  42. res.end(`${pathname} You are looking for is not found`);
  43. } else {
  44. res.setHeader('Content-Type', 'application/json;charset=UTF-8;');
  45. res.end(data);
  46. }
  47. });
  48. });
  49. } else {
  50. fs.readFile(__dirname + '/aside.json', (err, data) => {
  51. if (err) {
  52. res.statusCode = 404;
  53. res.end(`${pathname} You are looking for is not found`);
  54. } else {
  55. res.end(data);
  56. }
  57. });
  58. }
  59. }
  60. // 获取用户的信息
  61. if (pathname === '/api/get_user') {
  62. let urlObj = url.parse(req.url, true);
  63. let {u_id} = urlObj.query;
  64. fs.readFile(__dirname + '/user.json', 'utf8', function (err, data) {
  65. let dataArr = JSON.parse(data);
  66. let user = dataArr.find(item => +item.id === +u_id);
  67. if (user) {
  68. res.end(JSON.stringify({
  69. code: 0,
  70. data: {
  71. token: 'adsflkds1fldslafk'
  72. },
  73. msg: 'ok'
  74. }))
  75. } else {
  76. res.end(JSON.stringify({
  77. code: -1,
  78. data: {},
  79. msg: '用户不存在'
  80. }))
  81. }
  82. })
  83. }
  84. }
  85. });
  86. server.listen(8000, () => console.log('port 8000 is on'));

三、PromiseA+

实现一个Promise

  1. class MyPromise {
  2. constructor (executor) {
  3. // this 是当前类的实例
  4. // 当resolve执行时,会把当前实例上成功的事件池中的所有函数挨个执行
  5. // 给实例添加两个事件池,一个是装成功的事件函数,一个装失败的事件函数
  6. // 初始化一个状态 pending
  7. // 初始化一个值value
  8. this.state = 'pending';
  9. this.fulfilledEvent = [];
  10. this.rejectedEvent = [];
  11. this.value = undefined;
  12. let resolve = (result) => {
  13. // 循环事件池中的函数,让其按个执行
  14. // 修改状态,一旦状态发生变更就不能再修改状态
  15. if (this.state !== 'pending') return;
  16. this.state = 'fulfilled';
  17. this.value = result;
  18. setTimeout(() => {
  19. this.fulfilledEvent.forEach(fulfillCb => {
  20. if (typeof fulfillCb === 'function') fulfillCb(this.value);
  21. }, 0)
  22. })
  23. };
  24. // 当reject时,把实例上保存失败的事件池中的函数都执行了
  25. let reject = (reason) => {
  26. if (this.state !== 'pending') return;
  27. this.state = 'rejected';
  28. this.value = reason;
  29. let timer = setTimeout(() => {
  30. clearTimeout(timer); // 这里为啥要清除timer???
  31. this.rejectedEvent.forEach(rejectCb => {
  32. if (typeof rejectCb === 'function') rejectCb(this.value);
  33. })
  34. })
  35. };
  36. // 处理Promise的异常
  37. try {
  38. executor(resolve, reject);
  39. } catch (e) {
  40. reject(e)
  41. }
  42. }
  43. then (resolveFn, rejectFn) {
  44. // 如果then方法中没有传递resolveFn或者rejectFn,要自动补全
  45. if (!resolveFn) {
  46. resolveFn = result => result;
  47. }
  48. if (!rejectFn) {
  49. rejectFn = reason => {
  50. throw new Error(reason)
  51. }
  52. }
  53. return new MyPromise((resolve, reject) => {
  54. // 不是直接把函数放进去,因为需要判断当前函数是否返回一个Promise实例
  55. this.fulfilledEvent.push((result) => {
  56. try {
  57. let x = resolveFn(result);
  58. x instanceof MyPromise
  59. ? x.then(resolve, reject)
  60. : resolve(result);
  61. } catch (e) {
  62. reject(e)
  63. }
  64. });
  65. this.rejectedEvent.push(reason => {
  66. try {
  67. let x = rejectFn(reason);
  68. x instanceof MyPromise
  69. ? x.then(resolve, reject)
  70. : resolve(x); // 如果不是Promise实例,直接执行下一个then中的resolve
  71. } catch (e) {
  72. reject(e);
  73. }
  74. })
  75. })
  76. }
  77. }

使用

  1. new MyPromise((resolve, reject) => {
  2. console.log(1);
  3. reject('abc');
  4. }).then(function (res) {
  5. console.log(2);
  6. }, function (err) {
  7. console.log(3)
  8. }).then((res) => {
  9. console.log(4)
  10. }, function () {
  11. console.log(5)
  12. });
  13. console.log(6);

【发上等愿,结中等缘,享下等福,择高处立,寻平处住,向宽处行】