欢迎您访问新疆栾骏商贸有限公司,公司主营电子五金轴承产品批发业务!
全国咨询热线: 400-8878-609

新闻资讯

常见问题

JS Promise axios 请求结果后面的.then() 是什么意思

作者:用户投稿2026-01-11 06:16:25
目录
  • Promise 对象
    • Promise 对象的状态
    • 回调函数
    • Promise.then() 绑定回调函数
  • 使用 Promise:链式调用
    • 链式调用的实现
    • 错误处理
    • 常见错误
  • 创建 Promise 对象
    • Promise 其他静态方法
      • 创建已决议的 Promise 对象
      • 多个 Promise 对象
    • 结语&参考文献

      Promise 是JS中一种处理异步操作的机制,在现在的前端代码中使用频率很高。Promise 这个词可能有点眼生,但你肯定见过 axios.get(...).then(res => {...});用于异步请求的 axios 返回的就是一个 Promise 对象。

      平时一直在代码中 .then() .catch() 地写来写去,终于决定要认真学一学这个 Promise 到底是怎么回事,希望这篇学习笔记也能帮到你。

      Promise 对象

      一个 Promise 对象表示一个异步操作的执行结果,包括状态(成功/失败)和值(成功返回值/错误原因)。一个 Promise 在创建的时候异步操作可能还没执行完成,通过持有这个 Promise 对象,可以在未来异步操作完成的时候对结果进行相应操作。

      Promise 对象的状态

      这里有几个常用的名词,用来表示 Promise 对象当前的具体状态:

      Pending 待定:刚创建时的初始状态,还没有确定执行结果

      Fulfilled 已兑现:异步操作执行成功,并返回一个值

      Rejected 已拒绝:异步操作执行失败,并返回一个错误原因

      Settled 已敲定 / Resolved 已决议:“待定”状态的反面,都表示异步操作已经执行完成,即已兑现已拒绝

      回调函数

      如果完全不关心异步操作的执行结果,那就把它放在那自己执行就可以了;但通常情况下我们总是要对操作执行的结果进行后续处理的,例如更改页面上的数据显示、错误处理等。但由于异步操作不知道什么时候可以执行完成,就出现了“回调函数”的概念,意思就是等到异步操作处理结束了,再回过头来调用这个函数来对执行结果进行处理。

      传统做法是,在执行异步操作的时候就把回调函数作为参数传进去,比如最常见的:

      setTimeout(function(){
          console.log("成功!");
      }, 250);
      

      setTimeout() 函数是最常见的异步函数之一,众所周知它的作用就是在指定时间后执行指定代码。仔细看就会发现,setTimeout()函数接收两个参数,第二个参数是等待时间,而第一个参数就是回调函数,即等待指定的时间之后要回来调用这个函数。

      很显然这种传参的做法有很多不方便的地方,比如把对结果的后续处理和异步操作本身耦合在了一起,以及著名的回调地狱:

      doSomething(function(result) {
        doSomethingElse(result, function(newResult) {
          doThirdThing(newResult, function(finalResult) {
            console.log('Got the final result: ' + finalResult);
          }, failureCallback);
        }, failureCallback);
      }, failureCallback);
      

      Promise.then() 绑定回调函数

      有了 Promise 之后,就能把回调和异步操作本身分开了。无论一个 Promise 对象当前是否已经执行完毕,我们都能在它上面绑定回调函数,并且保证回调函数被执行;这就是喜闻乐见的 then() 方法。

      p.then(onFulfilled[, onRejected]);
      p.then(value => {
        // fulfillment
      }, reason => {
        // rejection
      });
      

      then() 方法的语法很简单,有两个可选参数,分别代表当 Promise 的状态变为成功(fulfilled)和失败(rejected)时所使用的回调函数。

      如果只想绑定 onRejected(即失败时的错误处理函数),下面两种写法完全等价,第二种是第一种的简写形式。

      p.then(null, failureCallback);
      p.catch(failureCallback);
      

      使用 Promise:链式调用

      如果只是用 then 来绑定回调函数,那并不能解决回调地狱的问题。然而很妙的地方来了:Promise 支持链式调用

      doSomething().then(function(result) {
        return doSomethingElse(result);
      })
      .then(function(newResult) {
        return doThirdThing(newResult);
      })
      .then(function(finalResult) {
        console.log('Got the final result: ' + finalResult);
      })
      .catch(failureCallback);
      

      链式调用的实现

      能做到链式调用的魔法来自 then() 方法:它会在执行相应的回调函数之后,返回一个新的 Promise 对象,并且插入 Promise 链的当前位置

      这里稍微有点绕,容易把回调函数等同于 then() 方法本身。实际上成功/失败的回调函数只是 then() 的参数而已;而实际执行 then() 的时候,它会先根据 promise 的状态调用相应的回调函数,再根据回调函数的执行结果生成一个新的 Promise 对象并返回;具体的对应规则如下:

      回调函数执行情况then() 返回的 Promise 对象
      返回值 return x;fulfilled 状态,参数为 x
      直接返回 return; / 无 return 语句fulfilled 状态,参数为 undefined
      抛出错误 throw err;rejected 状态,参数为 err
      返回已决议的 Promise状态和参数与返回的 Promise 一致
      返回未定的 Promise未定的 Promise,回调参数与返回的相同

      下面这个例子中,初始 Promise 的状态为已拒绝,然后第一个 then() 调用了绑定的 onRejected,返回了状态为 fulfilled 的新 Promise 对象,并传递给了链中的下一个 then():

      Promise.reject()
        .then(() => 99, () => 42) // 调用 onRejected(return 42;),表格中的第一种情况
        .then(solution => console.log('Resolved with ' + solution)); // Resolved with 42
      

      同时,你可能还记得 then() 的参数定义,两个回调函数都是可选的;如果没有传入对应的回调函数,then() 会直接把原 promise 的终态返回,不做额外处理。

      错误处理

      遇到异常抛出(被拒绝的 promise)时,浏览器会顺着 Promise 链寻找下一个 onRejected 回调函数(经常被简写为 .catch()),并跳过中间的 onFulfilled 回调函数。这种执行逻辑与同步代码中的 try-catch 执行过程非常相似:

      // 异步 Promise
      doSomething()
      .then(result => doSomethingElse(result))
      .then(newResult => doThirdThing(newResult))
      .then(finalResult => console.log(`Got the final result: ${finalResult}`))
      .catch(failureCallback);
      
      // 同步
      try {
        let result = syncDoSomething();
        let newResult = syncDoSomethingElse(result);
        let finalResult = syncDoThirdThing(newResult);
        console.log(`Got the final result: ${finalResult}`);
      } catch(error) {
        failureCallback(error);
      }
      

      一个具体的例子:

      Promise.resolve()
      .then(() => {
          throw new Error('出错');
          console.log('a');
      })
      .then(() => {
          console.log('b');
      })
      .catch(() => {
          console.log('c');
      })
      .then(() => {
          console.log('d');
      });
      
      // 输出结果:
      // "c"
      // "d"
      

      常见错误

      doSomething().then(function(result) {
        doSomethingElse(result) // 没有返回 Promise 以及没有必要的嵌套 Promise
        .then(newResult => doThirdThing(newResult));
      }).then(() => doFourthThing());
      // 最后,是没有使用 catch 终止 Promise 调用链,可能导致没有捕获的异常
      

      上面这个例子在 Promise 中进行了嵌套,但没有将嵌套的 Promise 对象返回,因此doFourthThing() 不会等待 doSomethingElse()或 doThirdThing() 完成,而是并行运行;并且如果有传入参数,接收到的会是 undefined 而不是 doThirdThing() 的执行结果。

      正确的写法应该是:

      注:箭头函数 () => x 是 () => { return x; } 的简写,即返回了新的 Promise 对象

      doSomething()
      .then(function(result) {
        return doSomethingElse(result);
      })
      .then(newResult => doThirdThing(newResult))
      .then(() => doFourthThing())
      .catch(error => console.log(error));
      

      创建 Promise 对象

      如果要执行的异步操作没有返回 Promise 对象,可以用 new 和构造器创建自己的 promise。构造器的两个参数的作用是在异步操作成功/失败时,转换 Promise 对象的状态并传递对应参数。

      const myFirstPromise = new Promise((resolve, reject) => {
        // 做一些异步操作,最终会调用下面两者之一:
        // resolve(someValue); // fulfilled
        // reject("failure reason"); // rejected
      });
      
      // 一个例子
      function myAsyncFunction(url) {
        return new Promise((resolve, reject) => {
          const xhr = new XMLHttpRequest();
          xhr.open("GET", url);
          xhr.onload = () => resolve(xhr.responseText);
          xhr.onerror = () => reject(xhr.statusText);
          xhr.send();
        });
      };
      

      Promise 其他静态方法

      创建已决议的 Promise 对象

      Promise.resolve(value) 和 Promise.reject(reason) 方法分别返回一个已经成功/失败的 Promise 对象。

      const p1 = new Promise((resolve, reject) => {
        resolve();
      });
      const p2 = Promise.resolve();
      

      如果 resolve(value) 的参数是带有 then() 方法的 Promise 对象,函数将返回其自带 then() 方法的执行结果;如果参数为空或是基本类型,返回的Promise对象与在 then() 方法中 return 对应值的结果一致,参见上文表格。基于这样的特性, resolve(value) 方法可以用于将不确定是否为 Promise 对象的 value 值统一为 Promise。

      多个 Promise 对象

      Promise.all(iterable)

      • 参数列表中的所有的 promises 都成功时,返回一个 fulfilled 的 Promise 对象,参数值是所有 promises 成功返回值的列表(顺序不变)
      • 如果任何一个 promise 失败,立即返回一个 rejected 的 Promise 对象,参数是这个失败 promise 的错误信息
      Promise.all([func1(), func2(), func3()])
      .then(([result1, result2, result3]) => { /* use result1, result2 and result3 */ });
      

      Promise.allSettled(iterable)列表中所有 promises 都已敲定后返回一个promise,并带有一个对象数组,对应每个promise 的结果。

      Promise.any(iterable)当列表中的任意一个 promise 成功时,立即返回这个 promise 的值。

      Promise.race(iterable)当列表中任意一个 promise 成功或失败时,立即返回该 promise 对象的执行结果。

      一个综合例子(使用 setTimeout 模拟异步操作):

      // 创造一个状态为 fulfilled,参数为"foo"的 Promise 对象
      Promise.resolve("foo")
        .then(function(string) {	// string: "foo"
          // 返回状态为 fulfilled,参数为"foobar"的对象
          return new Promise(function(resolve, reject) {
            setTimeout(function() {
              string += 'bar';
              resolve(string);
            }, 1);
          });
        })
        .then(function(string) {	// string: "foobar"
          setTimeout(function() {
            string += 'baz';
            console.log(string);
          }, 1)
          // 返回值"foobar"
          return string;
        })
        .then(function(string) {	// string: "foobar"
          console.log("Last Then");
          console.log(string);
        });
      
      // 输出结果:
      // Last Then
      // foobar
      // foobarbaz(由第二个 then 中的 setTimeout 输出)
      

      结语&参考文献

      以上是阅读学习了 MDN 文档后个人总结的学习笔记,可能存在错误和疏漏,欢迎指正与讨论!

      MDN-Promise

      MDN-使用Promise

      MDN-Promise.then()