Promise 详解

什么是 Promise?

Promise 是 JavaScript 中用于处理异步操作的对象,它代表一个异步操作的最终完成(或失败)及其结果值。

Promise 的三种状态

Promise 有三种状态,且状态一旦改变就不可逆转:

  1. pending(等待中)​​:初始状态,既不是成功,也不是失败

  2. fulfilled(已成功)​​:操作成功完成

  3. rejected(已失败)​​:操作失败

基本语法

复制代码
const promise = new Promise((resolve, reject) => {
  // 异步操作
  if (/* 操作成功 */) {
    resolve(value); // 将状态改为 fulfilled
  } else {
    reject(error); // 将状态改为 rejected
  }
});

Promise 的实例方法

1. .then()- 处理成功状态

复制代码
promise.then(
  (value) => {
    // 成功时的处理
    console.log('成功:', value);
  },
  (error) => {
    // 失败时的处理(可选)
    console.log('失败:', error);
  }
);

2. .catch()- 处理失败状态

复制代码
promise.catch((error) => {
  console.log('捕获错误:', error);
});

3. .finally()- 无论成功失败都会执行

复制代码
promise.finally(() => {
  console.log('无论成功失败都会执行');
});

实际应用示例

示例 1:模拟异步操作

复制代码
function fetchData() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const success = Math.random() > 0.3;
      if (success) {
        resolve('数据获取成功!');
      } else {
        reject('数据获取失败!');
      }
    }, 1000);
  });
}

// 使用 Promise
fetchData()
  .then(data => console.log(data))
  .catch(error => console.error(error))
  .finally(() => console.log('请求完成'));

示例 2:模拟 AJAX 请求

复制代码
function ajaxRequest(url) {
  return new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    xhr.open('GET', url);
    xhr.onload = () => {
      if (xhr.status === 200) {
        resolve(JSON.parse(xhr.responseText));
      } else {
        reject(new Error(`请求失败: ${xhr.status}`));
      }
    };
    xhr.onerror = () => reject(new Error('网络错误'));
    xhr.send();
  });
}

// 使用示例
ajaxRequest('https://api.example.com/data')
  .then(data => console.log(data))
  .catch(error => console.error(error));

Promise 的静态方法

1. Promise.all()- 所有 Promise 都成功

复制代码
const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve) => {
  setTimeout(resolve, 100, 'foo');
});

Promise.all([promise1, promise2, promise3])
  .then(values => {
    console.log(values); // [3, 42, "foo"]
  })
  .catch(error => {
    // 如果任何一个 Promise 被拒绝,立即拒绝
    console.error(error);
  });

2. Promise.race()- 第一个完成的 Promise

复制代码
const promise1 = new Promise((resolve) => {
  setTimeout(resolve, 500, '第一个');
});

const promise2 = new Promise((resolve) => {
  setTimeout(resolve, 100, '第二个');
});

Promise.race([promise1, promise2])
  .then(value => {
    console.log(value); // "第二个"
  });

3. Promise.allSettled()- 所有 Promise 都完成(无论成功失败)

复制代码
const promise1 = Promise.resolve(3);
const promise2 = new Promise((resolve, reject) => 
  setTimeout(reject, 100, '失败')
);

Promise.allSettled([promise1, promise2])
  .then(results => {
    results.forEach(result => console.log(result.status));
    // "fulfilled", "rejected"
  });

4. Promise.any()- 第一个成功的 Promise

复制代码
const promise1 = Promise.reject(0);
const promise2 = new Promise((resolve) => 
  setTimeout(resolve, 100, '快的')
);
const promise3 = new Promise((resolve) => 
  setTimeout(resolve, 500, '慢的')
);

Promise.any([promise1, promise2, promise3])
  .then(value => {
    console.log(value); // "快的"
  });

Promise 链式调用

复制代码
function asyncOperation1() {
  return new Promise(resolve => {
    setTimeout(() => resolve(10), 1000);
  });
}

function asyncOperation2(value) {
  return new Promise(resolve => {
    setTimeout(() => resolve(value * 2), 1000);
  });
}

function asyncOperation3(value) {
  return new Promise(resolve => {
    setTimeout(() => resolve(value + 5), 1000);
  });
}

// 链式调用
asyncOperation1()
  .then(result1 => {
    console.log('第一步结果:', result1); // 10
    return asyncOperation2(result1);
  })
  .then(result2 => {
    console.log('第二步结果:', result2); // 20
    return asyncOperation3(result2);
  })
  .then(result3 => {
    console.log('最终结果:', result3); // 25
  })
  .catch(error => {
    console.error('错误:', error);
  });

错误处理的最佳实践

复制代码
// 好的错误处理方式
fetchData()
  .then(data => {
    // 处理数据
    return processData(data);
  })
  .then(processedData => {
    // 使用处理后的数据
    console.log(processedData);
  })
  .catch(error => {
    // 统一处理所有错误
    console.error('操作失败:', error);
  });

// 避免这种写法(反模式)
fetchData()
  .then(data => {
    // 处理数据
  }, error => {
    // 这里的 catch 无法捕获 then 回调中的错误
    console.error(error);
  });

async/await 与 Promise

async/await 是 Promise 的语法糖,让异步代码看起来像同步代码:

复制代码
// 使用 Promise
function fetchUserData() {
  return fetch('/api/user')
    .then(response => response.json())
    .then(data => console.log(data))
    .catch(error => console.error(error));
}

// 使用 async/await
async function fetchUserData() {
  try {
    const response = await fetch('/api/user');
    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.error(error);
  }
}

常见面试题

1. Promise 的执行顺序

复制代码
console.log('1');

setTimeout(() => console.log('2'), 0);

Promise.resolve().then(() => console.log('3'));

console.log('4');

// 输出顺序: 1, 4, 3, 2
// 解释:同步代码 > 微任务(Promise) > 宏任务(setTimeout)

2. Promise 链式调用中的错误处理

复制代码
Promise.resolve()
  .then(() => {
    throw new Error('错误1');
  })
  .then(() => {
    console.log('这里不会执行');
  })
  .catch(error => {
    console.log('捕获错误:', error.message); // "错误1"
    throw new Error('错误2');
  })
  .catch(error => {
    console.log('再次捕获:', error.message); // "错误2"
  });

总结

Promise 的主要优势:

  1. 避免回调地狱​:使异步代码更易读和维护

  2. 更好的错误处理​:统一的错误处理机制

  3. 链式调用​:支持多个异步操作的顺序执行

  4. 并行处理 ​:通过 Promise.all()等方法实现并行操作

Promise 是现代 JavaScript 异步编程的基础,理解 Promise 对于掌握 async/await 和现代前端开发至关重要。

相关推荐
曹绍华2 天前
okhttp详解
okhttp
天花板之恋4 天前
Android http网络请求的那些事儿
http·okhttp
Entropless4 天前
解剖OkHttp:那些主流教程未曾深入的设计精髓
android·okhttp
介一安全5 天前
【Frida Android】实战篇3:基于 OkHttp 库的 Hook 抓包
android·okhttp·网络安全·frida
峰哥的Android进阶之路6 天前
Okhttp原理总结
okhttp
椰羊sqrt9 天前
CVE-2025-4334 深度分析:WordPress wp-registration 插件权限提升漏洞
android·开发语言·okhttp·网络安全
0和1的舞者9 天前
网络通信的奥秘:HTTP详解 (七)
服务器·网络·网络协议·http·okhttp·软件工程·1024程序员节
爱怪笑的小杰杰13 天前
浏览器端缓存地图请求:使用 IndexedDB + ajax-hook 提升地图加载速度
ajax·okhttp·缓存
没有故事、有酒13 天前
Ajax介绍
前端·ajax·okhttp