axios 和 PromiseA+

一、axios

1.1 axios是什么

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

1.2 安装axios库
    npm install axios --save 或者 yarn add axios --save
1.3.1 axios常用的方法:
  • 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.1Node静态资源服务器
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
    // 初始化一个值value

    this.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);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值