深入理解Promise/ajax

270 阅读2分钟

深入理解promise/ajax

Promise 对象特点

  1. 对象的状态不受外界影响。 Promise对象代表一个异步操作, 有三种状态: pending( 进行中)、 fulfilled( 已成功) 和rejected( 已失败)。 只有异步操作的结果, 可以决定当前是哪一种状态, 任何其他操作都无法改变这个状态。 一旦状态改变, 就不会再变, 任何时候都可以得到这个结果。 Promise对象的状态改变, 只有两种可能: 从pending变为fulfilled和从pending变为rejected。 只要这两种情况发生, 状态就凝固了, 不会再变了, 会一直保持这个结果, 这时就称为 resolved( 已定型)。 如果改变已经发生了, 你再对Promise对象添加回调函数, 也会立即得到这个结果。
  2. 一旦状态改变,就不会再变,任何时候都可以得到这个结果。 Promise对象的状态改变, 只有两种可能: 从pending变为fulfilled和从pending变为rejected。 只要这两种情况发生, 状态就凝固了, 不会再变了, 会一直保持这个结果, 这时就称为 resolved( 已定型)。 如果改变已经发生了, 你再对Promise对象添加回调函数, 也会立即得到这个结果。

Promise缺点

  1. 无法取消promise, 一旦新建它会立即执行, 无法中途取消。
  2. 如果不设置回调函数, promise内部抛出的错误, 不会反应到外部
  3. 当处于pending 状态时, 无法得知目前进展到那一阶段。

原生ajax

// 0 未初始化未调用open     
// 1.启动 调用open 未调用 send
// 2. 发送 已调用send() 但是未响应   
// 3. 接收 已经接收部分响应数据  
// 4.完成  完成全部数据响应 
const ajax = function (params) {
  if (!params.url) return
  const promise = new Promise((resolve, reject) => {
    const handler = function () {
      if (this.readyState !== 4) return
      if (this.status == 200) {
        resolve(this.responseText)
      } else {
        reject(this.statusText)
      }
    }
    const xhr = new XMLHttpRequest()
    if (params.method.toLowerCase() == 'get') {
      xhr.open('get', url + '?' + formatParams(params.data));
      xhr.send()
    } else {
      xhr.open('post', url);
      xhr.send(JSON.stringify(params.data));
    }
    xhr.onreadystatechange = handler xhr.responseType = 'json'
    xhr.setRequestHeader('Accept', 'application/json');
  })
  return promise

  function formatParams(obj) {
    if (!data) return
    var arr = []
    for (let i in obj) {
      arr.push(`${encodeURIComponent(i)}=${encodeURIComponent(obj[i])}`)
    }
    return arr.join('&')
  }
}

asyncpool Es6 实现

function asyncPool(poolLimit, array, iteratorFn) {
    let i = 0;
    const ret = [] // 存储所有的异步任务
    const executing = []; // 存储正在执行的异步任务
    const enqueue = function () {
      if (i === array.length) {
        return Promise.resolve();
      }
      const item = array[i++]; // 获取新的任务项
      const p = Promise.resolve().then(iteratorFn(item, array));
      ret.push(p)
      let r = Promise.resolve();
      if (poolLimit <= array.length) {
        const e = p.then(() => {
          return executing.splice(executing.indexOf(e), 1)
        })
        executing.push(e)
        if (executing.length >= poolLimit) {
          r = Promise.race(executing)
        }
      }
      return r.then(() => enqueue())
    }
    return enqueue().then(() => Promise.all(ret))
  }