JavaScript Promise 详解:从回调地狱到链式调用

作者:半夏

时间:2026-10-22

浏览:113

本文深入解析 JavaScript 中 Promise 对象的核心机制,涵盖 pending、resolved 和 rejected 三种状态转换。通过对比传统回调方式,展示如何利用 then、catch 及 Promise.all、Promise.race 等 API 解决回调地狱问题,实现优雅的异步链式调用与错误处理。

文章目录

背景:从回调地狱到异步优化

一、背景

Node.js 之所以运行高效,主要得益于其采用的异步回调机制处理等待事件,使代码无需阻塞即可继续执行。然而,当存在多层嵌套回调时,例如一个回调完成后触发下一个,再触发后续回调,代码结构会变得极其混乱,极易陷入所谓的“回调地狱”,导致代码难以维护。


async(1, function(value){
 async(value, function(value){
 async(value, function(value){
  async(value, function(value){
  async(value, function(value){
   async(value, final);
  });
  });
 });
 });
});

这种层层嵌套的写法令人头疼,是否有更好的解决方案?答案是肯定的。ES6 引入的 Promise 对象以及 ES7 的 async/await 语法均能有效解决此问题。本文将重点介绍 Promise 对象,async/await 将在后续文章中展开。

简介:Promise 的状态与核心概念

二、简介

Promise 是一个用于处理异步操作的对象,旨在使异步调用代码更加优雅、美观且易于阅读。正如其名“承诺”所示,使用 Promise 后,无论操作成功或失败,都会返回确定的结果,无需担心异步任务丢失。Promise 具有三种状态:pending(进行中)、resolved(已完成)和 rejected(已失败)。只有异步操作的结果才能改变其状态,因此 Promise 的状态变化通常只有两种路径:从 pending 变为 resolved,或从 pending 变为 rejected。

Promise 对象提供了一个常用的 then 方法,用于注册回调函数。then 方法接收两个参数:第一个是状态变为 resolved 时的成功回调,第二个是状态变为 rejected 时的失败回调,其中失败回调为可选参数。此外,then 方法内部可以返回另一个 Promise 对象,从而支持链式调用。接下来通过代码进行演示:


var Pro = function (time) {
   //返回一个Promise对象
   return new Promise(function (resolve, reject) {
    console.log('123');
    //模拟接口调用
    setTimeout(function () {
     //这里告诉Promise 成功了,然后去执行then方法的第一个函数
     resolve('成功返回');
    }, time);
   })
  };
  (function(){
   console.log('start');
   Pro(3000)
   .then(function(data){
    console.log(data);
    return Pro(5000);})
   .then(function(data){
    console.log(data);
    console.log('end');
   })
  })();

上述代码中,定义了一个 Pro 变量,并将其赋值为一个返回 Promise 对象的匿名函数。该函数接收 resolve 和 reject 两个参数,并通过 setTimeout 模拟异步请求。当执行 resolve 方法后,将触发 then 方法中的第一个回调函数。运行结果如下:

背景:从回调地狱到异步优化

API:Promise 常用方法与组合器

三、Promise 的 API

1. Promise.resolve() 2. Promise.reject() 3. Promise.prototype.then() 4. Promise.prototype.catch() 5. Promise.all():所有实例均完成时执行,逻辑上相当于“与”操作。 6. Promise.race():任一实例改变状态即返回,逻辑上相当于“或”操作。

1. Promise.resolve() 的作用是将现有对象转换为状态为 resolved 的 Promise 对象。例如:Promise.resolve('test') 等价于 new Promise(resolve => resolve('test'))。

2. Promise.reject() 同样返回一个 Promise 对象,但其初始状态为 rejected。

3. then 方法在前文已做介绍,此处不再赘述。

4. catch():用于捕获并处理发生错误的回调函数。

5. Promise.all() 适用于需要所有结果都完成后才执行 then 成功回调的场景。举例如下:


let p1 =new Promise(function(resolve,reject){
   resolve(1);
  });
  let p2 = new Promise(function(resolve,reject){
   resolve(2);
  });
  let p3 = new Promise(function(resolve,reject){
   resolve(3);
  });
  Promise.all([p1, p2, p3]).then(function (results) {
   console.log('success:'+results);
  }).catch(function(r){
   console.log("error");
   console.log(r);
  });

最终输出结果:

背景:从回调地狱到异步优化

6. Promise.race() 用于同时执行多个 Promise 实例,只要其中一个实例的状态发生改变,返回的 Promise 状态即跟随该实例的状态。

实战:链式调用示例

四、例子


var Pro = function () {
   //返回一个Promise对象
   return new Promise(function (resolve, reject) {
    //模拟接口调用
    setTimeout(function () {
     resolve(true);
    }, 1000);
   })
  };
  var Pro2 = function () {
   //返回一个Promise对象
   return new Promise(function (resolve, reject) {
    //模拟接口调用
    setTimeout(function () {
     resolve('Pro2成功执行');
    }, 1000);
   })
  };
  
  Pro().then(function(data){
   var val = data;
   console.log(val)
   if (val) {
    console.log(1111)
    return Pro2()
   }
   
  }).then(function(data1){
   console.log(data1)
  })

输出:

背景:从回调地狱到异步优化

通过 then 方法,我们可以轻松实现链式调用。

以上关于 JavaScript Promise 的详细介绍到此结束,希望能为读者提供参考,并欢迎大家支持本站。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章