zoukankan      html  css  js  c++  java
  • 16. Promise对象

    Promise对象

    一.含义

    1. Promise是什么

    • promise是异步编程的一种解决方案,比传统的异步解决方案【回调函数】和【事件】更合理,更强大,已被纳入ES6规范

    2. 实例讨论

    问题:发送多个异步请求 并且每个请求之间需要相互依赖

    1. 在传统方法中,使用回调函数,通过嵌套方式来解决这个问题

      • 问题:
      • 代码逻辑书写顺序与执行顺序不一致,不利于阅读与维护。
      • 异步操作的顺序变更时,需要大规模的代码重构。
      • 回调函数基本都是匿名函数,bug 追踪困难。
      • 回调函数是被第三方库代码(如上例中的 ajax )而非自己的业务代码所调用的,造成了 IoC 控制反转
      $.get(url, data1 => {
          console.log(data1)
          $.get(data1.url, data2 => {
              console.log(data1)
          })
      })
      
    2. Promise处理多个互相关联的异步请求

      const request = url => { 
          return new Promise((resolve, reject) => {
              $.get(url, data => {
                  resolve(data)
              });
          })
      };
      
      // 请求data1
      request(url).then(data1 => {
          return request(data1.url);   
      }).then(data2 => {
          return request(data2.url);
      }).then(data3 => {
          console.log(data3);
      }).catch(err => throw new Error(err));
      

    二.Promise特性案例解析

    1. Promise的立即执行性

    • promise对象表示未来将要发生的事件,但是在创建Promise对象时,作为参数的方法是会立即执行的,只是其中执行的代码可以是异步代码

    • 所以如下案例,create promise会先于after create promise执行

      var p = new Promise(function(resolve,reject){
          console.log('cerete promise');
          resolve('success');
      })
      
      console.log('after create promise');
      
      p.then(function(value){
          console.log(value);
      })
      
      //	create promise
      //	after create promise
      //	success
      

    2. promise的三种状态

    var p1 = new Promise(function(resolve,reject){
      resolve(1);
    });
    var p2 = new Promise(function(resolve,reject){
      setTimeout(function(){
        resolve(2);  
      }, 500);      
    });
    var p3 = new Promise(function(resolve,reject){
      setTimeout(function(){
        reject(3);  
      }, 500);      
    });
    
    console.log(p1);
    console.log(p2);
    console.log(p3);
    setTimeout(function(){
      console.log(p2);
    }, 1000);
    setTimeout(function(){
      console.log(p3);
    }, 1000);
    
    p1.then(function(value){
      console.log(value);
    });
    p2.then(function(value){
      console.log(value);
    });
    p3.catch(function(err){
      console.log(err);
    });
    
    • 返回值
    Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: 1}
    Promise {[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined}
    Promise {[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined}
    1
    2
    3
    Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: 2}
    Promise {[[PromiseStatus]]: "rejected", [[PromiseValue]]: 3}
    
    • promise有三种状态,pending,resolved,rejected
    • 当promise刚创建时,处于pending状态
    • 当promise中的参数函数执行resolve之后,promise由pending状态变为resolved状态
    • 当promise中的参数函数执行reject之后,那么promise中的pending状态变为rejected状态

    3. Promise的状态不可逆性

    var p1 = new Promise(function(resolve, reject){
      resolve("success1");
      resolve("success2");
    });
    
    var p2 = new Promise(function(resolve, reject){
      resolve("success");
      reject("reject");
    });
    
    p1.then(function(value){
      console.log(value);
    });
    
    p2.then(function(value){
      console.log(value);
    });
    
    • 返回结果
    success1
    success
    
    • promise中的状态一旦变成 resolved或者rejected之后,无论后续怎么调用resolve和reject方法,都无法改变promise的状态

    4. 链式调用

    var p = new Promise(function(resolve, reject) {
        resolve(1);
    });
    p.then(function(value) { //第一个then
        console.log(value);
        return value * 2;
    }).then(function(value) { //第二个then
        console.log(value);
    }).then(function(value) { //第三个then
        console.log(value);
        return Promise.resolve('resolve');
    }).then(function(value) { //第四个then
        console.log(value);
        return Promise.reject('reject');
    }).then(function(value) { //第五个then
        console.log('resolve: ' + value);
    }, function(err) {
        console.log('reject: ' + err);
    })
    
    • 返回结果
    1
    2
    undefined
    resolve
    reject:reject
    
    • promise的then方法,返回一个新的promise对象。因此可以通过链式条用then方法
    • then方法接受两个函数作为参数,第一个是promise执行成功的时候调用的方法,第二个是promise执行失败的时候调用的方法
    • 以上两个函数中,只有一个会被调用

    5. Promise then,回调异步性

    var p = new Promise(resolve,reject){
        resolve("success");
    };
    p.tnen(function(value){
        console.log(value);
    });
    console.log("which one is first~");
    
    • 返回结果
    which one is first~
    success
    
    • Promise接收函数是同步执行的,但是then方法中的函数是异步执行的,所以success是后面执行的

    6. Promise中的异常

    var p1 = new Promise(function(resolve, reject) {
    				foo.bar();
    				resolve(1);
    			});
    
    p1.then(
        function(value) {
            console.log('p1 then value: ' + value);
        },
        function(err) {
            console.log('p1 then err: ' + err);
        }
    ).then(
        function(value) {
            console.log('p1 then then value: ' + value);
        },
        function(err) {
            console.log('p1 then then err: ' + err);
        }
    );
    
    var p2 = new Promise(function(resolve, reject) {
        resolve(2);
    });
    
    p2.then(
        function(value) {
            console.log('p2 then value: ' + value);
            foo.bar();
        },
        function(err) {
            console.log('p2 then err: ' + err);
        }
    ).then(
        function(value) {
            console.log('p2 then then value: ' + value);
        },
        function(err) {
            console.log('p2 then then err: ' + err);
            return 1;
        }
    ).then(
        function(value) {
            console.log('p2 then then then value: ' + value);
        },
        function(err) {
            console.log('p2 then then then err: ' + err);
        }
    );
    
    • 返回值
    p1 then err: ReferenceError: foo is not defined
    p2 then value: 2
    p1 then then value: undefined
    p2 then then err: ReferenceError: foo is not defined
    p2 then then then value: 1
    
    • Promise中的异常由then的第二个参数函数进行处理,异常信息将作为promise的值
    • 异常一旦得到处理,then返回的后续Promise对象将恢复正常,并被promise执行成功的回调函数进行处理
    • 另外要注意的是p1,p2的多级then是交替执行的

    7. Promise.resolve()

    • Promise.resolve()可以接受一个值或者是一个promise对象
      • 当参数值为普通时,它返回一个resolved状态的promise对象,值为传的那个参数
      • 当参数值为promise对象时,它直接返回这个promise对象

    8. resolve VS reject

    var p1 = new Promise(function(resolve, reject){
      resolve(Promise.resolve('resolve'));
    });
    
    var p2 = new Promise(function(resolve, reject){
      resolve(Promise.reject('reject'));
    });
    
    var p3 = new Promise(function(resolve, reject){
      reject(Promise.resolve('resolve'));
    });
    
    p1.then(
      function fulfilled(value){
        console.log('fulfilled: ' + value);
      }, 
      function rejected(err){
        console.log('rejected: ' + err);
      }
    );
    
    p2.then(
      function fulfilled(value){
        console.log('fulfilled: ' + value);
      }, 
      function rejected(err){
        console.log('rejected: ' + err);
      }
    );
    
    p3.then(
      function fulfilled(value){
        console.log('fulfilled: ' + value);
      }, 
      function rejected(err){
        console.log('rejected: ' + err);
      }
    );
    
    
    • 返回结果
    p3 rejected: [object Promise]
    p1 fulfilled: resolve
    p2 rejected: reject
    
    • Promise回调函数中的第一个参数resolve,会对Promise执行’拆箱‘动作。即当resolve的参数是一个promise对象时,resolve会拆箱获取这个promise对象的值,但是这个过程是异步的。
    • Promise回调函数中的第二个参数reject不会进行拆箱操作,所以reject函数中的参数直接传递给then方法中的rejected回调

    三.Promise使用总结

    1. 初始化Promise对象

      • new Promise(fn)
      • Promise.resolve(fn)
    2. 调用上一步返回的promise实例对象的then方法,注册回调函数

      • then回调函数可以拥有一个参数,也可以不带参数。如果then中的回调函数依赖上一层返回的结果,那么要带上参数

        new Promise(fn)
        .then(fn(value){
              //处理过程
              })
        
    3. 最后注册 catch 异常处理函数,处理前面回调中可能抛出的异常。

  • 相关阅读:
    数据结构化与保存
    爬取基础2
    爬取校园新闻首页的新闻的详情,使用正则表达式,函数抽离
    爬虫基础
    中文词频
    使用docker搭建rabbitmq集群
    centos安装rabbitmq
    git查看仓库地址以及修改远程仓库
    网易云邮箱账号
    jmeter提取登录cookie实现跨线程组保持登录
  • 原文地址:https://www.cnblogs.com/mapengfei247/p/11116711.html
Copyright © 2011-2022 走看看