JavaScript Promise

什么是 Promise

Promise 是 ES6 引入的异步编程解决方案,用来替代层层嵌套的回调。可以把 Promise 理解成"一个承诺结果的容器":它代表一个尚未完成、但将来一定会完成(或失败)的异步操作。使用它能让异步代码结构清晰、错误处理统一。

三种状态

Promise 对象一生只有三种状态:

  • pending(进行中):初始状态,操作还没出结果。
  • fulfilled(已成功):操作完成,拿到了结果。
  • rejected(已失败):操作出错,拿到了失败原因。 状态只能从 pending 变为 fulfilled 或 rejected,一旦改变就不可再变,所以 then 里的回调只会被调用一次。

创建 Promise

构造时传入一个执行器函数,调用 resolve 表示成功、reject 表示失败:

var p = new Promise(function (resolve, reject) {
    var ok = true;        // 模拟请求结果
    if (ok) {
        resolve("数据加载成功"); // 进入 fulfilled
    } else {
        reject("请求失败");       // 进入 rejected
    }
});
p.then(function (data) {
    console.log(data); // 输出:数据加载成功
});

then / catch / finally

  • then:成功时执行,可返回新 Promise 继续链式调用。
  • catch:失败时执行,统一处理错误。
  • finally:无论成功失败都会执行,适合收尾。
p.then(function (data) {
    console.log("成功:" + data);
}).catch(function (err) {
    console.log("失败:" + err);
}).finally(function () {
    console.log("请求结束");
});
// 成功:数据加载成功
// 请求结束

链式调用解决回调地狱

每个 then 里 return 一个新的 Promise,就能把层层嵌套改成平铺的链:

getUser()
    .then(function (user) { return getOrder(user.id); })
    .then(function (order) { return getDetail(order.id); })
    .then(function (detail) { console.log(detail); })
    .catch(function (err) { console.log("出错:" + err); });

链上任何一环 rejected,就会直接跳到最后的 catch,错误不用层层传递。

Promise.all 与 Promise.race

处理多个并发异步任务:

// 全部成功才继续,结果为结果数组
Promise.all([getUser(), getConfig()]).then(function (results) {
    console.log(results[0], results[1]);
});
// 谁先完成就用谁的结果(常用于超时控制)
Promise.race([getData(), timeout(3000)]).then(function (first) {
    console.log("先到的是:" + first);
});

小结

Promise 把异步结果装进对象,用 then/catch/finally 链式处理,并用 all/race 管理并发,彻底告别回调地狱;下一节 async/await 会在此基础上把异步代码写得更简洁。

笔记加载中…