zoukankan      html  css  js  c++  java
  • ES6

     1.含义

    Promise是异步编程的一种解决方案。所谓Promise,简单来说就是一个容器,里面保存这某个未来才会结束的事件(异步操作)的结果。从语法上说,Promise是一个对象,从它可以获取异步操作的消息。Promise提供统一的API,各种异步操作都可以用相同的方法进行处理。

    (1)Promise对象的两个特点

    ① 对象的状态不受外界影响

    Promise对象代表一个异步操作,有三种状态:pending(进行中)fulfilled(已成功)rejected(已失败)。只有异步操作的结果可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。

    ②一旦状态改变,就不会再变,任何时候都可以得到这个结果

    Promise对象的状态改变,只有两种可能:从pending -> fulfilled和从pending -> rejected。只要这两种情况发生,状态就凝固了,不会再发生改变。

    后面的resolved统一只指fulfilled状态,不包含rejected状态。

    (2)缺点

    • 无法取消Promise,一旦新建它就会立即执行,无法中途取消。
    • 如果不设置回调函数,Promise内部抛出的错误,不会反应到外部
    • 当处于pending状态时,无法得知目前进展到哪一个阶段

    2.基本用法

    (1)创造一个Promise实例

    ES6规定,Promise对象是一个构造函数,用来生成Promise实例

     1 const promise = new Promise(function(resolve,reject){
     2 
     3     // 其他代码
     4 
     5     if(/* 异步操作成功 */){
     6         resolve(value)
     7     }else{
     8         reject(err)
     9     }
    10 })

    Promise构造函数接受一个函数作为参数,该函数有两个参数:resolverejected,它们是两个函数,由JavaScript引擎提供,不用自己部署:

    • resolve函数:作用是将Promise对象的状态从“未完成 -> 成功”,即pending -> resolve。在异步操作成功时调用,并将异步操作的结果作为参数传递出去
    • rejected函数:将Promise对象的状态从“未完成 -> 失败”,即pending -> rejected。在异步操作失败时调用,并将异步操作报的错误,作为参数传递出去

    Promise实例生成以后,可以用then方法分别指定resolved状态和rejected状态的回调函数

    promise.then(function(value){
      // 成功的回调
    },function(err){
      // 失败的回调
    });

    它们都接受Promise对象传出的值作为参数.

    示例:

     1     function timeout(ms) {
     2         return new Promise((resolve, reject) => {
     3             setTimeout(() => {
     4                 resolve("异步执行结束")
     5             }, ms)
     6         })
     7     }
     8 
     9     timeout(1000)
    10         .then((value) => { console.log(value) })  // 1s 后输出:异步执行结束

    上面代码中,timeout方法返回一个Promise实例,说明过一段时间才会发生结果。过了指定的时间(ms参数)以后,Promise实例的状态变为resolved,就会触发then方法绑定的回调函数。

    注意:Promise新建以后就会立即执行。

     1     let promise = new Promise(function (resolve, reject) {
     2         console.log("Promise");
     3         resolve()
     4     })
     5 
     6     promise.then(function () {
     7         console.log("异步结束");
     8     })
     9 
    10     console.log("hello world");
    11 
    12     // Promise
    13     // hello world
    14     // resolved

    上面代码中,Promise新建以后立即执行,所以首先输出Promise。然后.then方法的回调函数,将在当前脚本所在同步任务执行完才会执行,所以异步结束最后输出。这里涉及到JS的事件循环,详细可见

    注意:

    • 即使没有调用.then()方法,promise内的log方法也会执行:
    1     let promise = new Promise(function (resolve, reject) {
    2         console.log("Promise");
    3         resolve()
    4     })  // Promise
    •  调用resolve或rejected并不会终结Promise的参数函数的执行。
    1     let promise = new Promise(function (resolve, reject) {
    2         console.log("Promise");
    3         resolve()
    4         console.log("Promise仍在执行");
    5     }) 
    6      // Promise
    7      // Promise仍在执行
    • 一般来说,resolve以后,Promise的使命便结束了,后续操作应该放到.then方法里面,而不应该直接写在resolve或reject后面,所以最好加上return语句:
      • new Promise((resolve, reject) => {
          return resolve(1);
          // 后面的语句不会执行
          console.log(2);
        })

     3.Promise.prototype.then()

     then方法是定义在原型对象Promise.prototype上的。它的作用是为Promise实例添加状态改变时的回调函数。

     then方法的两个参数分别是resolved状态的回调函数和rejected状态的回调函数,它们都是可选的

    then方法返回的是一个新的Promise实例(不是原来的哪个Promise实例),因此可以使用链式写法(then后面接另一个then)

    getJSON("/json").then(function(json){
       return "json"
    }).then(function(){
      // ...
    })

    示例:

     1     let promise = new Promise(function (resolve, reject) {
     2         console.log("Promise");
     3         return resolve()
     4     }) 
     5 
     6     promise.then(function () {
     7         console.log("Promise结束");
     8         return "异步结束"
     9     }).then((res)=>{
    10         console.log(res);
    11     })
    12 
    13     // Promise
    14     // Promise结束
    15     // 异步结束

    说明:第一个回调函数完成以后,会将返回结果(“异步结束”)作为参数传入第二个回调函数

      采用链式的then,可以指定一组按照次序调用的回调函数。这时,前一个回调函数,有可能返回的还是一个Promise对象(即有异步操作),这时后一个回调函数,就会等待该Promise对象的状态发生变化,才会被调用。

    4.Promise.prototype.catch()

     Promise.prototype.catch()方法是.then(null, rejection).then(undefined, rejection)的别名,用于指定发生错误时的回调函数。

    getJSON('/posts.json').then(function(posts) {
      // ...
    }).catch(function(error) {
      // 处理 getJSON 和 前一个回调函数运行时发生的错误
      console.log('发生错误!', error);
    });

    上面说过Promise的状态从pending -> rejected状态时会将异步操作的错误作为参数传递出去:

    示例1:

     1     let promise = new Promise(function (resolve, reject) {
     2         console.log("Promise");
     3         return reject("发生不明错误")
     4     })
     5 
     6     promise.then(function () {
     7     }).catch(err => {
     8         console.log(err);
     9     })
    10 
    11     // Promise
    12     // 发生不明错误

    示例2:

    1     const promise = new Promise(function (resolve, reject) {
    2         throw new Error('test');
    3     });
    4     promise.catch(function (error) {
    5         console.log(error);
    6     });
    7     // Error:test

    其实reject()方法的作用,等同于抛出错误。

    注意:如果Promise状态已经变成了resolved,再抛出错误是无效的

    Promise对象的错误具有“冒泡新值”,会一直向后传递,直到被捕获位置。也就是说,错误总是会被下一个catch语句捕获。

     1 let promise = new Promise(function(resolve,reject){
     2     reject(123)
     3 })
     4 
     5 promise.then()
     6     .then()
     7     .then()
     8     .catch(err =>{
     9         console.log(err);
    10     })
    11     // 123

    建议:使用catch()方法,而不是使用then()方法的第二个参数来不湖泊then方法执行中的错误。

      因外第二种写法可以捕获前面then方法执行中的错误,也更接近同步的写法(try/catch)

    跟传统的try/catch代码块不同的是,如果没有使用catch()方法指定错误处理的回调函数,Promise对象抛出的错误不会传递到外层代码,即不会有任何反应。

     1 const someAsyncThing = function() {
     2   return new Promise(function(resolve, reject) {
     3     // 下面一行会报错,因为x没有声明
     4     resolve(x + 2);
     5   });
     6 };
     7 
     8 someAsyncThing().then(function() {
     9   console.log('everything is great');
    10 });
    11 
    12 setTimeout(() => { console.log(123) }, 2000);

    上面代码中,someAsyncThing()函数产生的Promise对象,内部有语法错误。浏览器运行到这一行,会打印出错误提示ReferenceError: x is not defined。但是不会退出进程,终止脚本运行,2s后还是会输出123。说明Promise内部的错误不会影响到Promise外部的代码,通俗说法就是"Promise 会吃掉错误"。

    一般总是建议,Promise 对象后面要跟catch()方法,这样可以处理 Promise 内部发生的错误。catch()方法返回的还是一个 Promise 对象,因此后面还可以接着调用then()方法。如上面的示例:

     1     const someAsyncThing = function () {
     2         return new Promise(function (resolve, reject) {
     3             // 下面一行会报错,因为x没有声明
     4             resolve(x + 2);
     5         });
     6     };
     7 
     8     someAsyncThing()
     9         .catch(function (error) {
    10             console.log('oh no', error);
    11         })
    12         .then(function () {
    13             console.log('carry on');
    14         });
    15     // oh no [ReferenceError: x is not defined]
    16     // carry on

    上面代码运行完catch方法指定的回调函数,会接着运行后面那个then()方法指定的回调函数。如果没有报错,则会跳过catch()方法

    Promise.resolve()
    .catch(function(error) {
      console.log('oh no', error);
    })
    .then(function() {
      console.log('carry on');
    });
    // carry on

    上面代码中,carch()方法抛出了一个错误,因为后面没有别的catch()方法了,所以这个then中的错误不会被捕获,也不会传递到外层。如果改写以下,结果就不一样了。

     1     const someAsyncThing = function () {
     2         return new Promise(function (resolve, reject) {
     3             // 下面一行会报错,因为x没有声明
     4             resolve(x + 2);
     5         });
     6     };
     7 
     8     someAsyncThing().then(()=>{
     9         return "hello"
    10     }).catch((err)=>{
    11         console.log("张三");
    12         y + 2
    13     }).catch(err=>{
    14         console.log("捕获错误:",err);
    15     })
    16     // 张三
    17     // 捕获错误: ReferenceError: y is not defined

    这里用的是第二个catch()用来捕获第一个catch()方法抛出的错误

  • 相关阅读:
    swagger-ui 系统配置过程(基于spring+springmvc+swagger+springfox配置 web-api 管理系统)
    如何简单扫描整理
    C#双面打印解决方法(打印wordexcel图片)
    MODI出现ORC RUNNING ERROR的解决方法
    EMGU 2.9.X在VS2010下调试真正靠谱的配置
    如何解决The underlying provider failed on Open问题
    shell编程之——cat /dev/null作用
    docker 容器的设置2
    docker 容器的设置1
    ssl证书生成与转换(pfx, pem, key, crt)
  • 原文地址:https://www.cnblogs.com/codexlx/p/14354307.html
Copyright © 2011-2022 走看看