zoukankan      html  css  js  c++  java
  • 异步编程——promise

    异步编程——promise

    定义

    Promise是异步编程的一个解决方案,相比传统的解决方法——回调函数,使用Promise更为合理和强大,避免了回调函数之间的层层嵌套,也使得代码结构更为清晰,便于维护。Promise 是一个对象,从他可以获取异步操作的消息,他也是一个容器,里面包含着事件结束之后要进行的操作。

    特点

    Promise对象有两个特点:

    • 对象的状态不收外界干扰。Promise对象有三种状态:pending(进行中)、resolved(已完成)、rejected(已失败),具体处于哪一种状态是由异步操作的结果来决定的,其他的任何操作都无法改变这个状态。
    • 一旦状态改变了,就不会再有其他的改变了,任何时候都能得到这个结果。Promise对象状态的改变有两种:1>.pending状态到resolved状态;2>.pending状态到rejected状态;

    用法

    Promise是一个构造函数,生成一个实例。

    var promise = new Promise(function(resolve,reject){
      if(/异步成功/){
      	resolve(val);
      }else{
     	 reject(val);
      }
    });
    promise.then(function(val){
    /成功后执行的函数/
    },function(error){
    /失败后执行的函数/
    });
    

    Promise构造函数接收一个函数作为参数,这个函数有两个参数resolve、reject,这两个参数也是两个函数,有javascript引擎提供,不需要自己实现。其中,resolve函数的作用是将Promise对象的状态由"进行中"变为"已完成",在异步操作成功的时候调用,并将异步操作的结果以参数的形式传出,就是上例中的val。reject函数的作用是将Promise对象的状态由"进行中"变为"已失败",在异步操作失败的时候调用,并将操作失败的错误已参数的形式传出。

    Promise的实例可以调用then方法,then方法有两个函数作为参数,第一个函数是Promise对象状态变为resoloved时执行的函数,第二个函数是Promise对象状态变为rejected时执行的函数,第二个参数是可选的。

    一个典型的例子:异步读取文件

    function readFileFn(filename){
      return new Promise(function(resolve,reject){
        fs.readfile(filename,function(err,data){
          if(err){
          	reject(err);
          }else{
          	resolve(data);
          }
        });
      });
    }
    readFileFn("./test.txt").then(function(data){
      console.log(data.toString());
      //其他操作...
      },function(err){
      	console.log(err);
    });
    

    then方法可以采用链式的写法,即:

    promise.then(...).then(...).then(..)

    具体的例子:

    var promise = new Promse(function(resolve,reject){
    	resolve(1);    //将Promise对象的状态改为resolved,并传递参数1
    });
    promise.then(function(val){
    	console.log(val);  // 1
    	return val*3;
    }).then(function(val){
    	console.log(val);  //3
    	return val*3;
    }).then(function(val){
    	console.log(val);  //9
    });
    

    Promise对象的一些其他方法

    • Promise.prototype.catch:用于指定发生错误时的回调函数,通常的用法是在then方法里省略第二个参数,然后在链式调用的尾部使用catch方法来捕获异步操作或者then方法中的错误;
    readFileFn("./test.txt").then(function(data){
      console.log(data.toString());
      //其他操作...
    }).catch(function(err){
    	console.log(err);
    })
    //另一种用法
    var promise = new Promise(function(resolve,reject){
    	reject(new Error("test"));
    });
    promise.then(function(val){
    	//...
    }).catch(function(err){
    	console.log(err);
    	//..
    });
    
    • Promise.all():次方法用于将多个Promise实例包装成一个新的Promise实例。Promise.all()方法接收一个数组作为参数:

    var p = Promise.all([a,b,c]);  //a,b,c都是Promise的实例

    p最终的状态由a,b,c三者决定:

    1>.当a,b,c的状态都是resolved时,p的状态才是resolved,此时a,b,c的返回值组成一个数组,传给p的回调函数。

    2>.只要 a,b,c中有一个状态时reject,p的状态就是reject,此时一个reject的实例的返回值会传递给p的回调函数。

    var promises = [1,2,3,4].map(function(id){
    	return readFileFn("./test"+id+".txt");  //readFileFn()是上面声明过的函数
    });
    Promise.all(promises).then(function(val){
    	//...
    }).catch(function(err){
    	//...
    });
    
    • Promise.race():同样是将多个Promise实例包装成一个新的Promise实例,与Promise.all()方法类似;
    • Promise.resolve():将一个非Promise对象转换为一个Promise对象,

    var promise = Promise.resolve($.ajax("./test.txt"));

    Promise.resolve()有四种类型的参数:

    1>.Promise实例,那么函数不会对参数做任何修改,原样返回;

    2>.普通对象,如同上例,会转换成一个promise对象返回;

    3>.非对象,即普通的变量,比如"hello"、2 等等,此时会返回一个新的Promise实例,状态为resolved(),"hello"会以参数的形式传给then的第一个方法;

    var p = Promise.resolve("hello");
    p.then(function(val){        //此函数会立即执行
      console.log(val);  //hello
    });
    

    4>.不带参数,会直接返回一个Resolved状态的Promise对象。

    • Promise.reject():返回一个状态为rejected的实例,参数类似于Promise.resolve()方法的第三种参数。
    • done():Promise内部的错误不会冒泡到全局,所以,如果回调链的最后一个出现错误,就无法被捕获,所以有了done()方法,位于回调链的最尾端,用于捕获错误。

    promise.then(function(){}).then(function(){}).catch(function(){}).done();

    • finally():指定不管Promise最后的状态如何都会执行的操作,他与done()的区别是可以接受一个普通的回调函数作为参数,且该函数一定会执行。
  • 相关阅读:
    yzoj P2344 斯卡布罗集市 题解
    yzoj P2350 逃离洞穴 题解
    yzoj P2349 取数 题解
    JXOI 2017 颜色 题解
    NOIP 2009 最优贸易 题解
    CH 4302 Interval GCD 题解
    CH4301 Can you answer on these queries III 题解
    Luogu2533[AHOI2012]信号塔
    Luogu3320[SDOI2015]寻宝游戏
    Luogu3187[HNOI2007]最小矩形覆盖
  • 原文地址:https://www.cnblogs.com/dan-dan/p/6675382.html
Copyright © 2011-2022 走看看