ECMAScript6 入门 Promise

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

定义
Promise:简单来说就是一个容器,里面保存着一个未来才会结束的事情(一个异步操作)的结果
(首先他是一个对象,保存一个异步操作的消息)

    特点:
    1:对象的状态不受外界影响 
        Promise对象代表着一个异步操作
        1:pending进行中
        2:fulfilled已成功
        3:rejected已失败
        只有异步操作的结果可以决定当前是哪一种状态
(promise对象的状态由异步操作的结果决定)
    2:一旦状态改变,就不会再变(从pending变为fulfilled和从pending变为rejected)
    (如果结果已经改变了,再去给promise对象添加回调函数,还是会得到这个结果
而事件的特点是错过了,再去监听,是得不到结果的)
    缺点:
    1:一旦新建它就会立即执行
    2:其次,如果不设置回调函数,Promise内部抛出的错误,不会反应到外部
    3:当处于pending状态时,无法得知目前进展到哪一个阶段

 

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

基本用法
Promise对象是一个构造函数,用来生成promise实例,
构造函数接受一个函数作为参数,
参数函数又接受resolve和reject作为参数,这两货也是函数
const promise = new Promise(function(resolve, reject) {
  // ... some code

  if (/* 异步操作成功 */){
    resolve(value); //从pending变为fulfilled
  } else {
    reject(error); //从pending变为rejected
  }
});
resolve函数的作用,将promise对象的状态从“未完成”变成“成功”,在异步操作成功时调用,并将异步操作的结果,作为参数传递出去
reject函数的作用,将promise对象的状态从“未完成”变成“失败”,在异步操作成功时调用,并将异步操作报出的错误,作为参数传递出去

** resolve和reject只是修改promise对象的状态,至于状态改变以后的回调函数,是定义在then当中

 

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

Promise实例生成以后,可以用then方法分别指定resolved状态和rejected状态的回调函数
then方法可以接受两个回调函数作为参数,两个函数都接受promise对象传出的值作为参数
第一个回调函数是Promise对象的状态变为resolved时调用,
第二个回调函数是Promise对象的状态变为rejected时调用,第二个函数是可选的
promise.then(function(value) {
  // success
}, function(error) {
  // failure
});

1:调用resolve和reject并不会终结promise的参数函数执行,在他们两之后的代码还是会正常执行
(但是我们建议在其之后不要执行相关操作,而放在回调函数当中执行,可以再调用前面加上return)
2:当p1和p2都是promise的实例时,但是p2的resolve方法将p1作为参数的情况下,p1的状态将会决定p2的状态执行 const p1 = new Promise(function (resolve, reject) { setTimeout(() => reject(new Error('fail')), 3000) }) const p2 = new Promise(function (resolve, reject) { setTimeout(() => resolve(p1), 1000) }) p2 .then(result => console.log(result)) .catch(error => console.log(error)) // Error: fail 最后会执行p2的catch方法

 

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

Promise.prototype.then()
1:Promise 实例具有then方法,也就是说,then方法是定义在原型对象
2:then方法返回的是一个新的Promise实例,所以可以采用链式调用的形式,(会将前一个then方法的返回值作为下一个promise对象的传入值)
3:then的第二个参数是可选的,
可以看下then方法的源码是如何定义
this.then = function (onFulfilled, onRejected) { var self = this; return new Promise(function (resolve, reject) { return self.done(function (result) { if (typeof onFulfilled === 'function') { try { return resolve(onFulfilled(result)); } catch (ex) { return reject(ex); } } else { return resolve(result); } }, function (error) { if (typeof onRejected === 'function') { try { return resolve(onRejected(error)); } catch (ex) { return reject(ex); } } else { return reject(error); } }); }); }

 

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

Promise.prototype.catch()
Promise.prototype.catch方法是.then(null, rejection)或.then(undefined, rejection)的别名,
用于指定发生错误时的回调函数
另外,then方法指定的回调函数,如果运行中抛出错误,也会被catch方法捕获
promise对象的错误具有冒泡性质,会一直向后传递,直到被捕获

所以推荐尽量then方法的第二个参数省略,将所有的错误统一使用catch进行抛出

 

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

Promise.prototype.finally()
finally方法用于指定不管 Promise 对象最后状态如何,都会执行的操作
finally方法的回调函数,不接受任何参数,所以里面的操作都是与状态没有关系
promise
.then(result => {···})
.catch(error => {···})
.finally(() => {···});
不管promise最后的状态,在执行完then或catch指定的回调函数以后,都会执行finally方法指定的回调函数
他的本质就是then方法的特例,成功和失败两种情况执行的代码一样就是finally

 

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

Promise.all()
Promise.all方法用于将多个 Promise 实例,包装成一个新的 Promise 实例
const p = Promise.all([p1, p2, p3]);
只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数
只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数

  Promise.race()
  Promise.race方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例

  

  Promise.resolve()
  将一个现有的对象转换成promise对象
  参数的四种情况
  1:参数是promise实例,那么不做任何改变
  2:thenable对象(指携带了then方法的对象),会将其转换成promise对象,并且立刻执行then方法
  3:不具有then方法的对象,甚至都不是对象,返回一个新的promise对象,并且状态为resolved
  4:不带有参数的情况,和3同样

  Promise.reject()
  将会返回一个新的promise实例,该实例的状态为rejected
  注意:该方法的参数,会原封不动的作为reject的参数,就是状态为rejected时回调函数的参数

 

  Promise.try()
  我们不想区分函数是否是同步还是异步,都想用then方法指定下一步流程,catch方法处理函数抛出的错误
  Promise.try(() => database.users.get({id: userId}))
  .then(...)
  .catch(...)

 

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

应用
1:加载图片
const preloadImage = function (path) {
  return new Promise(function (resolve, reject) {
    const image = new Image();
    image.onload  = resolve;
    image.onerror = reject;
    image.src = path;
  });
};

2:Generator 函数与 Promise 的结合
function getFoo () {
  return new Promise(function (resolve, reject){
    resolve('foo');
  });
}

const g = function* () {
  try {
    const foo = yield getFoo();
    console.log(foo);
  } catch (e) {
    console.log(e);
  }
};

function run (generator) {
  const it = generator();

  function go(result) {
    if (result.done) return result.value;

    return result.value.then(function (value) {
      return go(it.next(value));
    }, function (error) {
      return go(it.throw(error));
    });
  }

  go(it.next());
}

run(g);

 

posted @ 2019-09-26 18:09  初心不负  阅读(358)  评论(0编辑  收藏  举报