zoukankan      html  css  js  c++  java
  • Promise用法

    1. 引入原因

        js(nodejs)的耗时请求(如sql和file)都是异步返回。如果调用嵌套太多,则会造成“地狱回调”如下:

    sayhello("a", function(err){
        sayhello("b", function(err){
            sayhello("c", function(err){
                sayhello("d", function(err){
                    sayhello("e", function(err){
                        console.log("end");
                    });    
                });
            });
        });
    });
    

      js想通过一种方案使得以上问题得以解决,得到如下的调用样式。

    sayhello("a")
    .then(value=>
        {
            sayhello("b");
        })
    .then(value=>
        {
            sayhello("c");
        })
    .then(value=>
        {
            sayhello("d");
        })
    .then(value=>
        {
            sayhello("e");
        })
    .then(value=>
        {
            sayhello("end");
        });
    

     

    2. 基本用法

        Promise的构造函数的参数接受2个参数,都是函数。一个是resolve一个是reject。resolve函数将promise的状态职位fulfilled,reject将promise的状态置为rejected。

        这两个函数的具体实现实在then中。如下:

    console.log("1111 ");
    new Promise((resolve,reject)=>{
        setTimeout(() => {
            if(true)
                resolve("3333 resolved")
            else
                reject("3333 rejected");
            console.log("2222");//此处的2222,在3333world之前输出。
        }, 2000);
    })
    .then(value=>{
        console.log(value+':resolved')
    },value=>{
      console.log(value+":rejected");
    });
    

      

    3. 链式调用(返回的是个promise类型)。then中的resolve函数是直接返回的一个非promise的类型,那么这个返回值会作为下一个then的输入参数。

    const p = new Promise(function(resolve,reject){
      resolve(1);
    }).then(function(value){ // 第一个then // 1
      console.log(value);
      return value * 2;
    }).then(function(value){ // 第二个then // 2
      console.log(value);
    }).then(function(value){ // 第三个then // undefined
      console.log(value);
      return Promise.resolve('resolve'); 
    }).then(function(value){ // 第四个then // resolve,value是个string类型
      console.log(value);
      return Promise.reject('reject'); 
    }).then(function(value){ // 第五个then //reject:reject,value是个string类型
      console.log('resolve:' + value);
    }, function(err) {
      console.log('reject:' + err);
    });
    

      

    3. 关于2个参数。
        then或者promise的构造函数中都可以使用两个参数,resolve函数是必须的,reject函数是可选的。一般不用reject函数,对于错误的处理直接用catch比较简便。catch的用法参考下面。
     
    4.then返回一个promise。
       这是promise解决的最重要的“地狱回调”的问题。连环调用querySQL中,用此方法可以使代码可读性增加。返回promise实例,会使得之前的promise被取代。相当于下一个then前新建了一个promise实例。
    new Promise( resolve => {
        setTimeout( () => {//等效于读数据库场景
            resolve('hello');//直接运行
        }, 2000);
    })
    .then( value => {
        console.log(value);
        return new Promise( resolve => {
            setTimeout( () => {
                resolve('world');
                console.log("---")//---先于world world 输出
            }, 2000);
        });
    })
    .then( value => {
        console.log( value + ' world');
    });
    

      

    5. 一个实例(参考慕课网)
    console.log('here we go');
    new Promise(resolve => {
        setTimeout( () => {
            resolve('hello');
        }, 2000);
    })
        .then( value => {
            console.log(value);
            console.log('everyone');
            (function () {
                return new Promise(resolve => {
                    console.log("---")
                    setTimeout(() => {
                        console.log('Mr.Laurence');
                        resolve('Merry Xmas');//这里不输出,因为这个promise没有返回,所以他跟下面的then无关。
                    }, 2000);
                });
            }());
            return false;
        })
        .then( value => {
            console.log(value + ' world');
        });
    

      输出为

    here we go
    hello
    everyone
    ---
    false world
    Mr.Laurence
     
    6. catch用法。一般简易使用catch来捕获reject函数,不建议使用promise或者then的第二个函数参数。如下:
    new Promise( (resolve,reject) => {
        setTimeout( () => {
            console.log("111")
            if(true)    {
                resolve("success");
            }
            else {
                reject("error");//如果执行了reject,则会直接跳到最后一个catch
            }
        }, 200);
    })
    .then( value => {
        console.log( "222" + value);
        new Promise( (resolve,reject) => {
            setTimeout( () => {
                console.log("333")
                if(true)    {
                    resolve("success");
                }
                else {
                    reject("error");
                }
            }, 200);
        })    
    })
    .catch( error => {
        console.log( 'My Error:', error);
    });
    

      

    7. catch后面可以继续then,因为catch也会返回一个promise,将catch理解为reject函数即可。

    new Promise(resolve => {
        setTimeout(() => {
            resolve();
            //throw new Error('test error');//这里不能调用throw,这里只能用reject函数
        }, 1000);
    })
    .then( () => {
        console.log('start');
        throw new Error('test error');
    })
    .catch( err => {
        console.log('I catch:', err.message);
        // 下面这一行的注释将引发不同的走向
        // throw new Error('another error');
    })
    .then( () => {
        console.log('arrive here');
    })
    .then( () => {
        console.log('... and here');
    })
    .catch( err => {
        console.log('No, I catch:', err);
    });
    

     

    8.promise.all([])

  • 相关阅读:
    android开发布局三(微信布局)
    Android开发adb,SQLite数据库运用
    直线电机磁负荷、电负荷
    MIT公开课(一):电场和偶极子
    哈工大电气工程系硕士研究生入学复试——自动控制原理1、2章
    直线电机与旋转电机的区别
    Math类介绍
    Scala编辑器和IntelliJ IDEA开发环境配置
    减少cpu的方法
    AS内存清理,建议以及查找内存泄露的方法
  • 原文地址:https://www.cnblogs.com/dongfangchun/p/11414406.html
Copyright © 2011-2022 走看看