zoukankan      html  css  js  c++  java
  • 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);
    不忘初心,不负梦想
  • 相关阅读:
    MOSS发生“未能转换部分或所有标识引用”错误的处理
    Excel嵌入网页(二) 转载
    GridView的PagerTemplate分页
    深入探讨:如何理解.Net的三层架构(转)
    IIS报Service Unavailable错的解决方案
    浅谈C#托管程序中的资源释放问题(转)
    C#程序节省内存
    网页中嵌入Excel控件(补充)
    解决ajax的status=0问题
    翻开我的博客之旅
  • 原文地址:https://www.cnblogs.com/panrui1994/p/11593516.html
Copyright © 2011-2022 走看看