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更好。

原文地址:https://www.cnblogs.com/psxiao/p/11469856.html