• JavaScript Promise返回值详解


    JavaScript Promise返回值详解
    Promise回顾
    Promise回调函数返回非Promise值
    Promise回调函数返回Promise对象
    Promise回调函数中抛出错误
    总结
    Promise回顾
    Promise对象是JavaScript ES6标准中一个重要的内容,它是为了异步而生的,相比于经典的回调函数写法,在处理大量异步任务时使用Promise链在可读性上会远远优于回调函数导致的回调地狱,本文建立在读者已经对Promise有所了解的情况下,如果你还不了解Promise,可以参考MDN上的这篇文章。

    下面我们先来简要回顾一下Promise对象的性质,如果你已经足够熟悉,请前往下一节内容。

    Promise有三种状态,如果用Promise()构造器创建一个Promise对象,当被创建时,它的状态是pending,如果一个Promise对象的resolve方法被调用,它的状态会变成fulfilled,而如果一个Promise对象的reject方法被调用,它的状态会变成rejected。此外,还有两种初始化Promise对象的方法,分别是Promise.resolve方法和Promise.reject方法,前者会直接返回一个状态为fulfilled的Promise对象而后者会直接返回一个状态为rejected的Promise对象。

    在一个Promise链中,如果一个Promise状态变成了fulfilled,它会自动在Promise链中向下寻找,直到发现一个then方法,并执行其中的第一个参数函数,而如果一个Promise的状态变成了rejected,它会在Promise链中向下寻找,直到发现一个带有两个参数的then方法并执行它的第二个参数函数或发现一个catch方法并执行它的参数函数。

    要知道,Promise.prototype.then和Promise.prototype.catch都会返回一个Promise对象,这是Promise链能生效的关键,这篇文章讨论的重点就是这两个方法的返回值。

    注意:为了增强可读性,本文中涉及到Promise.prototype.then都只传入一个参数,作为fulfilled状态的回调函数,rejected状态的回调函数在Promise.prototype.catch中定义。

    Promise回调函数返回非Promise值
    当一个Promise.prototype.then方法被调用时,且在回调函数中返回的值是一个非Promise对象时,它会生成一个状态为fulfilled的新的Promise对象,并把该返回值传入下一个回调函数,看下面这个例子:

    Promise.resolve().then(function() {
      return 'Hello World';
    })
    .then(function(value) {
      console.log(`fulfilled: ${value}`); // 'fulfilled: Hello World'
    })
    .catch(function(value) {
      console.log(`rejected: ${value}`);
    });

    我们先用Promise.resolve生成了一个fulfilled状态的Promise对象以便调用then方法,在它的回调函数中我们返回了一个字符串Hello World,可以看到Promise链中第二个then方法的回调函数被调用,打印出了fulfilled: Hello World,说明前一个回调函数的返回值被传入,且在Promise链的上一环节返回的新Promise状态为fulfilled。

    当一个Promise.prototype.catch方法被调用,且在回调函数中返回的值是一个非Promise对象,它仍然会生成一个状态为fulfilled的新的Promise对象,并把该返回值传入下一个回调函数,相当于错误已经被捕获,看下面这个例子:

    Promise.reject().catch(function() {
      return 'Hello World';
    })
    .then(function(value) {
      console.log(`fulfilled: ${value}`); // 'fulfilled: Hello World'
    })
    .catch(function(value) {
      console.log(`rejected: ${value}`);
    })

    我们先用Promise.reject生成了一个rejected状态的Promise对象,这时第一个catch方法触发,在它的回调函数里返回了字符串Hello World,此后第一个then方法触发,打印出了fulfilled: Hello World,说明前一个回调函数的返回值被传入,且在Promise链的上一环节返回的新Promise状态为fulfilled。

    你可以动手试试上面的例子,自己尝试着修改一些代码并查看返回值,有助于对这一节的内容有更深的理解。

    Promise回调函数返回Promise对象
    如果Promise的回调函数中返回的是Promise,那么无论触发的是Promise链中的then方法还是catch方法,新生成的Promise对象的状态都直接取决于回调函数中返回的Promise对象的状态,传进下一个回调函数的值也取决于这个被返回的Promise对象,让我们看下面几个例子:

    Promise.resolve().then(function() {
      return Promise.resolve('Hello World');
    })
    .then(function(value) {
      console.log(`fulfilled: ${value}`); // 'fulfilled: Hello World'
    })
    .catch(function(value) {
      console.log(`rejected: ${value}`);
    });
    Promise.resolve().then(function() {
      return Promise.reject('Hello World');
    })
    .then(function(value) {
      console.log(`fulfilled: ${value}`);
    })
    .catch(function(value) {
      console.log(`rejected: ${value}`); // 'rejected: Hello World'
    });
    Promise.reject().catch(function() {
      return Promise.resolve('Hello World');
    })
    .then(function(value) {
      console.log(`fulfilled: ${value}`); // 'fulfilled: Hello World'
    })
    .catch(function(value) {
      console.log(`rejected: ${value}`);
    });
    Promise.reject().catch(function() {
      return Promise.reject('Hello World');
    })
    .then(function(value) {
      console.log(`fulfilled: ${value}`);
    })
    .catch(function(value) {
      console.log(`rejected: ${value}`); // 'rejected: Hello World'
    });

    你可以动手试试上面的例子来更深刻地感受一下返回Promise对象与返回其他值时的不同。

    通过这几个例子可以看到,如果回调函数中返回Promise对象,无论是then方法还是catch方法生成的Promise对象都直接取决于回调函数中的这个Promise对象。

    Promise回调函数中抛出错误
    如果Promise的回调函数中抛出了一个错误,则会生成一个状态为rejected的Promise,并将这个错误作为参数传给Promise链的下一个回调函数,看下面两个例子:

    Promise.resolve().then(function() {
      throw new Error('Oops!');
    })
    .then(function(value) {
      console.log('fulfilled');
      console.log(value.message);
    })
    .catch(function(value) {
      console.log('rejected'); // 'rejected'
      console.log(value.message); // 'Oops!'
    });
    Promise.reject().catch(function() {
      throw new Error('Oops!');
    })
    .then(function(value) {
      console.log('fulfilled');
      console.log(value.message);
    })
    .catch(function(value) {
      console.log('rejected'); // 'rejected'
      console.log(value.message); // 'Oops!'
    })

    你可以动手试试来感受一下这种情况下抛出错误对生成的Promise对象的影响。

    可以看到,这种情况下catch的回调函数被执行,说明抛出错误后,返回的Promise状态是rejected,并且传入Promise链下一环节的值是这个错误对象。

    总结
    当Promise的回调函数返回非Promise对象的值时,then和catch都生成一个状态为fulfilled的Promise对象,并把该返回值传入Promise链的下一环节。
    当Promise的回调函数返回值为Promise对象时,生成的Promise对象的状态由被返回的Promise对象决定,传入Promise链下一环节的值也由这个被返回的Promise决定。
    当Promise的回调函数中抛出错误时,then和catch都生成一个状态为rejected的Promise对象,并把抛出的错误对象传入Promise链的下一环节。

  • 相关阅读:
    mybatis集成spring
    静态代码块-普通代码块-构造代码块(好多图)
    Mybatis generator(复制粘贴完成)
    委派模式和适配器模式
    mysq--索引模块
    谈谈TCP的四次挥手
    说说TCP的三次握手
    网络基础知识
    java的IO机制
    std::bind接口与实现
  • 原文地址:https://www.cnblogs.com/onesea/p/15992324.html
Copyright © 2020-2023  润新知