zoukankan      html  css  js  c++  java
  • promise的用法

    首先理解一下异步和同步:

    异步:

    js是单线程的,只有一个主要的任务流程处理我们的js程序

    把一些耗时的事情通过新开线程的方式来实现,就是采用异步方法。

    异步任务有:setTimeout、setInterval、ajax,像ajax的事情还没有处理完成,也不会影响当前页面的其他行为。

    同步:当前线程直接处理

    异步任务一般采用回调的方式,

    常常遇到问题:callback hell:回到地狱。解决办法:promise

    promise:构造函数,通过promise来构建一个异步处理对象。

    // var a = 1;
            let p1 = new Promise ((resolve,reject)=>{
              // 要执行的异步任务
              /*
               resolve:函数,当我们调用该函数的时候。可以把当前Promise对象的任务状态改成resolved
               reject:函数,当我们调用该函数的时候,可以把当前的Promise对象的任务状态改成rejected
               只要Promise的任务状态发生了变化,这个Promise对象的then方法就会被执行
              */
              setTimeout(() =>{
                  a=10;
                  // setTimeout执行完之后就更改promise的状态
                  // resolve();//resolved
                  reject();//rejected
              },2000);
           });
            p1.then(()=>{
                //then方法就是Promise处理任务以后继续执行的任务,
                //then方法第一个参数是用来处理成功的,第二个参数是用来处理失败的
                console.log(a)
            },()=>{
                console.log('失败了')
            })

    Promise对象
        基本使用
        new Promise(function(resolve, reject) {
            // ... 要执行的(异步)任务
        })

    Promise状态:[[PromiseStatus]]
        - pending:初始状态,既不是成功,也不是失败状态
        - fulfilled/resolved:意味着操作成功完成
        - rejected:意味着操作失败

    Promise状态:[[PromiseStatus]]
        - resolve()函数:更改Promise对象为成功状态
        - reject()函数:更改Promise对象为失败状态

    then方法
        任务后续处理函数,一般情况下处理某个Promise任务完成(无论是成功还是失败)的后续任务
        .then(onFulfilled/onResolved, onRejected)
            onFulfilled/onResolved:fulfilled/resolved状态下调用
            onRejected:rejected状态下调用

    Promise值:[[PromiseValue]]
        任务处理完成(成功或失败),返回的值
            通过 resolve()、reject() 函数传入
                resolve(1)、reject(1)
            onFulfilled/onResolved, onRejected 函数接收
                .then(val=>console.log(val), ...)
    注意:

       new Promise(()=>{
                 setTimeout(()=>{
                     var a = 10;
                     resolve();
                 },2000);
            }).then(()=>{
                // 这样会报错,undefined,因为这里的a和setTimeout的a分别是两个函数里的a,不是同一个变量
                console.log(a)
            });
    //问题,如何将异步任务中产生的数据扔给then()函数执行呢:
            // 解决方法:resolve,reject这两个函数是可以传入参数的,传入的参数将被传递给then中的函数使用
            new Promise((resolve,reject)=>{
                 setTimeout(()=>{
                     var a = 10;
                     resolve(a);
                 },2000);
            }).then(v=>{
                // 这样会报错,undefined,因为这里的a和setTimeout的a分别是两个函数里的a,不是同一个变量
                console.log(v)
            });

    Promise Chain

    then函数执行后会返回一个新的Promise对象
            - 如果then没有传入处理函数,那么会返回一个继承了上一个处理状态的 Promise 对象

     new Promise((resolve,reject) =>{
                reject();
            }).then().then(()=>{
                console.log(0)
            },() =>{
                console.log(1)
            })
    // 结果是打印出1

     如果then传入处理函数,那么默认返回一个 fulfilled/resolved 状态的 Promise 对象

    new Promise((resolve,reject) =>{
                   reject();
               }).then(()=>{
                   console.log(1)
               },()=>{
                   console.log(2)
               }).then(()=>{
                   console.log(3)
               },() =>{
                   console.log(4)
               })
    结果:2 3

    如果then传入了处理函数,通过处理函数显示的return了一个新的 Promise,那么返回这个显示的 Promise 对象

     new Promise((resolve,reject) =>{
               reject();
           }).then(()=>{
               console.log(1);
           },()=>{
               console.log(2);
               return new Promise((resolve,reject)=>{
                   reject();
               })
           }).then(()=>{
               console.log(3)
           },() =>{
               console.log(4)
           })
    结果:2 4
    new Promise((resolve,reject) =>{
           resolve();
       })
       .then(() => {
           console.log('登录成功')
           //获取权限
           return new Promise((resolve,reject) =>{
             //如果是管理员,则成功,调用resolve()
               // resolve();
               if(false){
                   resolve();//无法解决中途终止后续执行的问题
               } else{
                   reject();
               }
           })
       },() => {
           console.log('登录失败')
       })
       .then(() => {
           console.log('是管理员')
           //获取资源
           return new Promise((resolve,reject) =>{
               resolve();
           })
       },() => {
           console.log('不是管理员')
       
       })
       .then(() => {
           console.log('拿到资源')
       },() => {
           console.log('不能获取资源')
       })

    问题:
            不易中途终止后续任务执行

    new Promise((resolve,reject) =>{
           // resolve();
           reject('第一步错误')
       })
       .then(() => {
           console.log('登录成功')
           //获取权限
           return new Promise((resolve,reject) =>{
             //如果是管理员,则成功,调用resolve()
               // resolve();
               if(false){
                   resolve();//无法解决中途终止后续执行的问题
               } else{
                   reject();
               }
           })
       })
       .then(() => {
           console.log('是管理员')
           //获取资源
           return new Promise((resolve,reject) =>{
               resolve();
           })
       })
       .then(() => {
           console.log('拿到资源')
       }).catch(err => {//catch执行完毕之后也会返回一个成功的状态的promise,所以他会继续执行catch后面then的第一个参数
           console.log(err)
       });

    .catch方法
        处理 rejected 的情况,与 then 的第二个参数 onRejected 相同
        返回一个 Promise 对象,状态默认为 fulfilled/resolved
        可以捕获 catch 之前的 Promise Chain 中的任一错误(如果 Promise Chain 中的 then 没有处理的话)

    all属性:

    多任务处理
            Promise.all(iterable)
            iterable:包含多个 Promise 的迭代器对象,比如数组
        当迭代器对象中的所有 Promise 状态都会 fulfilled/resolved 的时候,整体才是 fulfilled/resolved,否则就是 rejected

     let p1 = new Promise((resolve,reject)=>{
         setTimeout(()=>{
             console.log(1)
             resolve(10);
         },2000);
     })
    
     let p2 = new Promise((resolve,reject)=>{
         setTimeout(()=>{
             console.log(2)
             resolve(20);
         },3000);
     })
    // all属性表示,等p1,p2任务完成之后再执行then函数,
    //arr表示的是p1,p2值得集合
    Promise.all([p1,p2]).then(arr => {
        console.log(3,arr);//10,20
    })
    
    //race属性:只要p1p2中一个执行完了就会马上执行then方法
    Promise.race([p1,p2]).then(arr => {
        console.log(3,arr);//10
    })

    返回一个指定状态得promise对象

    Promise.resolve(1).then((v)=>{
        console.log(1)
    },()=> {
        console.log(2)
    })
    //结果为:1

    异步函数:

    //await必须在异步函数中才能执行 
              async function fn() {//表示异步函数
                   var v = await getValue(10);//await表示等当前得代码执行完毕才执行下面得代码
                   console.log(v);
    
            //可以通过return来终止继续执行后面得代码
                   var v = await getValue(10);//await表示等当前得代码执行完毕才执行下面得代码
                   console.log(v);
                   try{//js中可以将可能会出错的代码放到try语句中,然后用catch捕获异常的错误
                        var v = await getValue(200);//await表示等当前得代码执行完毕才执行下面得代码
                      console.log(v);
                   }.catch(e){
                       console.log(e)
                   }
              }
              function getValue(val){
                  return new Promise ((resolve,reject) =>{
                      setTimeout(()=>{
                          /*var a = 10;
                          resolve(val*10);*/
    
                          if(val < 100){
                              resolve(val*10);
                          } else{
                              reject('传入的值太大了')//浏览器会报错,可以用try解决
                          }
    
                      },2000)
                  });
              }
              fn();

    ES7 - async
        - await 操作符
        - async 函数

        await 必须 在 async 函数中才能使用
        await 后面可以是任意值,但是一般跟 Promise 对象
            - Promise 的 resolve 方法的值就是 await 值
            - Promise 的 reject 不会作为值返回,需要使用 try...catch 进行捕获

    promise的缺点:首先,无法取消Promise一旦新建它就会立即执行,无法中途取消。其次,如果不设置回调函数,promise内部抛出的错误,不会反应到外部。第三,当处于pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。如果某些事件不断地反复发生,一般来说,使用Stream模式比promise更好。

  • 相关阅读:
    iphone界面详解
    Spring jdbcTemplate.queryForInt(sql)的奇怪问题,呵呵
    BCP 高效批量导入
    eclipse中javascript显示为乱码的解决办法
    spring jdbcTemplate返回RS
    Spring IOC DI 形象理解
    MOSS 2007 文档库事件处理
    showModalDialog和showModelessDialog使用心得
    XMLHTTP.open权限不够的解决
    体现JAVA中的面向对象思想,接口(抽象类)的用处 :饲养员给动物喂食物
  • 原文地址:https://www.cnblogs.com/psxiao/p/11469856.html
Copyright © 2011-2022 走看看