关于promise以及自己实现一个promise

373 阅读1分钟

es6.ruanyifeng.com/ juejin.cn/post/684490…

# 'ok' .Promise 在resolve语句后面,再抛出错误,不会被捕获,等于没有抛出。因为 Promise的状态一旦改变,就永久保持该状态,不会再变了。
new Promise(function (resolve, reject) {
  resolve('ok')
  throw new Error('err')
}).then(console.log).catch(console.error)

# 同一个then中的作为第二个参数的函数捕捉不到作为第一个参数的函数中抛出的错误
new Promise(function (resolve, reject) {
  resolve('ok')
}).then(function (val) {
  console.log(1, val)
  throw '1err'
}, function (err) {
  console.log(2,err)
})

# then方法内的函数的返回值和下面关于Promise.resolve3中讨论一致。
return 普通值和 return出来promise有什么区别:return 普通值会立即是resolved状态,并把该值作为参数传给下一个then。
return promise的话,该promise的状态就决定了then的状态,他resolve的值作为下一个then函数的参数。

# Promise.resolve 1如果参数是 Promise 实例,那么将不做任何修改、原封不动地返回这个实例。

# Promise.resolve 2参数是一个普通对象或常量(包括undefined)时,生成一个新的 Promise 对象的实例,状态从一生成就是resolved,同时该参数会传给then的函数 
Promise.resolve().then(a=>{
  console.log('a', a) // undefined
})

# Promise.resolve 3参数是一个thenable对象时, 会将这个对象转为 Promise 对象,然后就立即执行thenable对象的then方法。
let thenable = {
  then: function(resolve, reject) {
    // return 33; // 如果这里return 一个普通值的话,永远不会resolve,下面的p1就进不了then
    resolve(42);
  }
};

let p1 = Promise.resolve(thenable);
p1.then(function(value) {
  console.log(value);  // 42
});

自己实现一个promise

github.com/xieranmaya/…

function MyPromise(executor) {
  var self = this
  self.status = 'pending'
  self.data = undefined
  self.onResolvedCbs = []
  self.onRejectedCbs = []

  function resolve(value) {
    if (self.status === 'pending') {
      self.status = 'resolved'
      self.data = value
      for(var i = 0; i < self.onResolvedCbs.length; i++) {
        self.onResolvedCbs[i](value)
      }
    }
  }

  function reject(reason) {
    if (self.status === 'pending') {
      self.status = 'rejected'
      self.data = reason
      for(var i = 0; i < self.onRejectedCbs.length; i++) {
        self.onRejectedCbs[i](reason)
      }
    }
  }

  try {
    executor(resolve, reject)
  } catch(e) {
    reject(e)
  }

}

MyPromise.prototype.then = function (onResolved, onRejected) {
  let self = this
  let promise2

  onResolved = typeof onResolved === 'function' ? onResolved : function (v) {return v}
  onRejected = typeof onRejected === 'function' ? onRejected : function (v) { throw v}

  if (self.status === 'resolved') {
    return promise2 = new MyPromise(function (resolve, reject) {
      try {
        let x = onResolved(self.data)

        if (x instanceof MyPromise) {
          x.then(resolve, reject)
        }

        resolve(x)
      } catch(err){
        reject(err)
      }
    })
  }

  if (self.status === 'rejected') {
    return promise2 = new MyPromise(function (resolve, reject) {
      try {
        let x = onRejected(self.data)

        if (x instanceof MyPromise) {
          x.then(resolve, reject)
        }

        resolve(x)
      } catch(err){
        reject(err)
      }
    })
  }

  if (self.status === 'pending') {
    return promise2 = new MyPromise(function (resolve, reject) {
      self.onResolvedCbs.push(function () {
        try {
          let x = onRejected(self.data)

          if (x instanceof MyPromise) {
            x.then(resolve, reject)
          }

          resolve(x)
        } catch(err){
          reject(err)
        }
      })

      self.onRejectedCbs.push(function () {
        try {
          let x = onRejected(self.data)

          if (x instanceof MyPromise) {
            x.then(resolve, reject)
          }

          resolve(x)
        } catch(err){
          reject(err)
        }
      })
    })
  }
}

用async await实现 promise.all

es6.ruanyifeng.com/#docs/async…

# 多个await命令后面的异步操作,如果不存在继发关系,最好让它们同时触发。
// 写法一
let [foo, bar] = await Promise.all([getFoo(), getBar()]);

// 写法二
let fooPromise = getFoo();
let barPromise = getBar();
let foo = await fooPromise;
let bar = await barPromise;

# 如果确实希望多个请求并发执行,可以使用Promise.all方法。当三个请求都会resolved时,下面两种写法效果相同。

async function dbFuc(db) {
  let docs = [{}, {}, {}];
  let promises = docs.map((doc) => db.post(doc));

  let results = await Promise.all(promises);
  console.log(results);
}

// 或者使用下面的写法

async function dbFuc(db) {
  let docs = [{}, {}, {}];
  // 这个地方已经执行请求了
  let promises = docs.map((doc) => db.post(doc));

  let results = [];
  for (let promise of promises) {
    results.push(await promise);
  }
  console.log(results);
}