zoukankan      html  css  js  c++  java
  • ES6随笔--Promise

    基础

    ES6原生提供了Promise对象,用来保存某个异步操作的结果。其状态不受外界影响,且状态一旦改变,就不会再变化。

    可能的状态:

    • pending 进行中
    • fulfilled 已成功
    • rejected 已失败

    状态改变:

    • pending-->fulfilled
    • pending-->rejected

    状态一旦发生改变就会定型,称为resolved。如果改变已经发生,再对Promise对象添加回调函数,也会立即得到这个结果。

    Promise创建后无法取消,pending状态下也无法得知进度。

    创建Promise实例:

    const promise = new Promise(function(resolve, reject){
        .....
        if (/*操作成功*/) {
            resolve(value);
        } else {
            reject(error);
        }
    }); 
    

    其中,Promise参数为一个函数,函数的两个参数分别是JS提供的resolvereject函数;

    resolve函数将Promise状态变为resolved;在异步操作成功时调用,并将异步操作的结果作为参数传递出去;

    reject函数将Promise状态变为rejected;在操作失败时调用,并将操作失败报出的错误,作为参数传递出去。

    设置这两个函数的回调函数

    promise.then(function (value){
        // 成功回调
    }, function (error) {
        // 失败回调
    });
    

    一个Ajax实例

    const getJson = function (url) {
            const promise = new Promise(function(resolve, reject){
              const handler = function () {
                if (this.readyState !== 4) {
                  return;
                }
                if (this.status === 200) {
                  resolve(this.responseText);
                } else {
                  reject(new Error(this.statusText));
                }
              }
              const XHR = new XMLHttpRequest();
              XHR.open("GET", url, true);
              XHR.responseType = "json";
              XHR.onreadystatechange = handler;
              XHR.setRequestHeader("Accept", "application/json");
              XHR.send()
            });
            return promise;
          }
          getJson("posts.json").then(function(json){
            console.log("Contents: "+json);
          }, function (error) {
            console.error("Error: ", error);
          });
    

    Promise.prototype.then()

    Promise实例添加状态改变时的回调函数,返回一个新的Promise对象,可以采用链式写法,指定一组按照次序调用的回调函数;

    注意then()方法必须接收一个函数作为参数,否则then()方法就会被视为then(null),不会起作用.

    // 以下输出为1
          Promise.resolve("1").then(Promise.resolve("2")).then(Promise.resolve("3"))
          .then(function (value) {
            console.log(value);
          });
    

    Promise.prototype.catch()

    `then(null, rejection)的别名。用于指定发生错误时的回调函数;

    Promise对象的错误具有冒泡性质,出现错误后会不停向后传递直到被捕获为止;但如果没有用catch方法指定回调函数,Promise对象内部的错误不会传递到外部;

    一般建议Promise对象后面要跟catch方法,这样可以处理Promise对象内部的错误;该方法返回的还是一个Promise对象。

    建议在then方法中定义resolve方法,而在catch方法中定义Reject状态的回调函数。

    promise.then(function (value) {
        //resolve函数
    }).catch(function (error) {
        //reject函数
    });
    

    Promise.prototype.finally()

    添加不论Promise对象最终的状态是Resolved还是Rejected都会执行的函数;

    Promise.all()

    用于把多个Promise实例,包装成一个新的Promise实例。参数必须是有Iterator接口的结构,且返回的成员都为Promise实例。对于数组参数,如果有不是Promise对象的项,会先调用promise.resolve()方法将其转为Promise对象。

    参数中所有的Promise对象的状态是逻辑与的关系,只有都变成了fulfilled,总的Promise对象的状态才会变成fulfilled,所有返回值组成数组传给总对象的回调函数;

    而只要有一个是rejected,总的Promise对象也会变为rejected,第一个被reject的实例的返回值被传给总对象的回调函数。

    Promise.race()

    同样是将多个Promise对象包装成一个Promise对象,但是参数对象只要有一个状态发生改变,总函数对象就会跟着改变,并把这个参数对象的返回值传递给总对象的回调函数;

    Promise.resolve()

    参数情况:

    • Promise实例--该方法直接返回该实例;
    • 不是Promise实例,但具有then方法--把该对象变成Promise实例,并立即执行其then方法;
    • 不是具有then方法的对象--返回一个新的Promise对象,状态为resolved,参数会传给回调函数;
    • 没有参数--直接返回一个resolved状态的Promise对象;

    关于执行时机:

    立即resolve的Promise对象是在本轮“事件循环”结束时,而不是下一轮“事件循环”开始时;(setTimeout()的回调函数是下一轮“事件循环”开始时)。

          setTimeout(function () {console.log("setTimeout out1")}, 0);
          Promise.resolve().then(function () {
            console.log("Promise out1");
          });
          console.log("direct 1");
          setTimeout(function () {console.log("setTimeout out2")}, 0);
          Promise.resolve().then(function () {
            console.log("Promise out2");
          });
          console.log("direct 2");
    
          // direct out1
          // direct out2
          // Promise out1
          // Promise out2
          // setTimeout out1
          // setTimeout out2
    

    Promise.reject()

    该方法返回一个状态为rejected的Promise对象,并把参数直接传递给回调函数,立即执行。

    Promise.try()

    模拟try代码块,可以捕捉同步或异步的错误:

    Promise.try(function () {
        ......
    }).then(function (value) {
        ......
    }).catch(function (error) {
        ......
    })
    

    Promise的深入理解

    参考:We have a problem with promises

    1. Promise对象的then()方法会返回一个新的Promise对象,then()方法的参数如果不是函数,会直接被视为then(null)对待;

    2. 作为.then()方法的参数的函数中,如果没有使用return返回某些值,将不会把结果输出到下一个方法中(undefined),该方法变成同步方法,下一个then中的回调函数将不会等待这个函数执行结束;建议始终在then()方法的参数中始终使用returnthrow

    3. 可能返回的合理的值包括:

      • 一个新的Promise对象;
      • 一个同步的值;
      • 抛出一个同步的错误;
    4. 使用Promise.resolve()Promise.reject(), 可以方便地返回一个立即resolvedrejected的Promise对象,用其封装一些同步方法可以很好地管理then()和捕捉错误;

    function somePromiseAPI() {
        return Promise.resolve().then(function () {
            doSomeThingThatMayThrow();
            return "foo";
        }).then(/*.......*/);
    }
    
    1. then(resolve, reject)中的reject回调函数只捕捉调用then()的Promise对象内的错误,而不会捕捉resolve函数中的错误;而.then(resolve, reject).catch(function (erroe)...)可以捕捉Promise对象和回调函数中的错误;

    2018-5-26

    生如夏花般绚烂,死如秋叶般静美
  • 相关阅读:
    50个jQuery 插件可将你的网站带到另外一个高度
    Web 开发中 20 个很有用的 CSS 库
    【算法】1、约瑟夫环
    智造微博
    银河系中央超大黑洞可能是个虫洞 其连接着两个不同的时空。
    创意文案:我害怕阅读的人
    解决Oracle ORA-00984: column not allowed here
    舌尖上的程序员
    技术贴 本地代码与svn关联教程 svn upgrade问题解决
    Aimp3的播放列表 按评分排序 落雨
  • 原文地址:https://www.cnblogs.com/muTing/p/9191633.html
Copyright © 2011-2022 走看看