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 天前
spiderdemo第四题
爬虫·okhttp·webassembly
Elieal3 天前
AJAX 知识
前端·ajax·okhttp
咖啡の猫6 天前
Vue 实例生命周期
前端·vue.js·okhttp
Jeled9 天前
Retrofit 与 OkHttp 全面解析与实战使用(含封装示例)
android·okhttp·android studio·retrofit
Jeled10 天前
Android 网络层最佳实践:Retrofit + OkHttp 封装与实战
android·okhttp·kotlin·android studio·retrofit
allk5512 天前
OkHttp源码解析(一)
android·okhttp
allk5512 天前
OkHttp源码解析(二)
android·okhttp
aFakeProgramer12 天前
拆分PDF.html 办公小工具
okhttp
一壶浊酒..14 天前
ajax局部更新
前端·ajax·okhttp