ES6 Promise对象详解:状态、链式调用与常用方法
本文深入解析ES6中的Promise对象,阐述其作为异步操作代理的核心机制。详细讲解Pending、Resolved和Rejected三种状态转换,演示then方法的链式调用及错误传递特性,并逐一介绍Promise.all、Promise.resolve及catch方法的实际应用场景与注意事项。
本文详细介绍ES6中Promise对象的具体用法,旨在为开发者提供实用的参考与示例。
Promise基本概念与状态机制
1. Promise的基本概念
Promise是一个JavaScript对象,其基本用法与其他对象无异。它主要充当代理(proxy),在异步操作与回调函数之间建立中介机制。通过提供同步操作的接口,Promise使得异步流程具备同步代码的执行逻辑,从而避免了回调函数层层嵌套的问题。
其核心思想在于:每个异步任务立即返回一个Promise实例。由于返回动作是即时的,程序可以沿用同步操作的执行流程。该对象包含一个then方法,用于指定异步任务完成后的回调函数。
假设有一个异步操作f1,它返回一个Promise对象,其对应的回调函数f2的调用方式如下。
(new Promise(f1)).then(f2);
2. Promise的三种状态
Promise对象存在三种可能的状态: ① 异步操作尚未完成(Pending) ② 异步操作已成功完成(Resolved) ③ 异步操作执行失败(Rejected)
3. 运行机制
通过then方法为Promise添加回调函数。该方法可接收两个回调:第一个用于处理状态转为Resolved(成功)的情况,第二个用于处理状态转为Rejected(失败)的情况,其中第二个参数可选。一旦状态发生切换,系统将自动调用相应的回调,并将异步操作的结果或错误作为参数传入。
promise.then(
console.log,
console.error
);
then方法的链式调用与错误处理
4. then方法的链式调用
① 由于then方法返回一个新的Promise对象,因此支持链式写法。
② then方法的第一个参数对应Resolved状态的回调,第二个参数(可选)对应Rejected状态的回调。
③ 如下示例所示,当Promise状态变为resolved后,会依次执行后续then指定的回调。每一步操作必须等待前一步执行完毕才会继续。最后一个then中的console.log与console.error存在重要区别:console.log仅显示回调函数step3的返回值,而console.error可以捕获step1、step2或step3中任意环节发生的错误。这表明Promise具有错误传递特性。
promise
.then(step1)
.then(step2)
.then(step3)
.then(
console.log,
console.error
);
Promise构造函数与Ajax应用
5. Promise的实际应用
var promise = new Promise(function(resolve, reject) { // promise的构造函数,Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject
// 异步操作的代码
if (/* 异步操作成功 */){
resolve(value);//将异步的操作结果作为参数传递出去
} else {
reject(error);
}
});
其中,resolve和reject是两个由JavaScript引擎内置提供的函数,无需开发者自行实现。
resolve函数的作用是将Promise状态从“未完成”(Pending)转变为“成功”(Resolved)。它在异步操作成功时调用,并将操作结果作为参数传递出去。
reject函数的作用是将Promise状态从“未完成”(Pending)转变为“失败”(Rejected)。它在异步操作失败时调用,并将报错信息作为参数传递出去。
① 以下示例展示了使用Promise实现Ajax请求的方法。
var getJSON = function(url) {
var promise = new Promise(function(resolve, reject){
var client = new XMLHttpRequest();
client.open("GET", url);
client.onreadystatechange = handler;
client.responseType = "json";
client.setRequestHeader("Accept", "application/json");
client.send();
function handler() {
if (this.readyState !== 4) {
return;
}
if (this.status === 200) {
resolve(this.response);//会将参数传递给回调函数
} else {
reject(new Error(this.statusText));
}
};
});
return promise;
};
getJSON("/posts.json").then(function(json) {
console.log('Contents: ' + json);
}, function(error) {
console.error('出错了', error);
});
② resolve函数的参数除了常规值外,还可以是另一个Promise实例。这意味着一个异步操作的结果可能是返回另一个异步操作。
var p1 = new Promise(function (resolve, reject) {
// ...
});
var p2 = new Promise(function (resolve, reject) {
// ...
resolve(p1);
})
catch方法捕获错误
6. Promise.prototype.catch()方法
① 如果异步操作抛出错误,Promise状态将变为Rejected,此时会调用catch方法指定的回调函数来处理该错误。
promise.then(function(posts) {
// ...
}).catch(function(error) {
// 处理 getJSON 和 前一个回调函数运行时发生的错误
console.log('发生错误!', error);
});
② 此外,若then方法中指定的回调函数在运行过程中抛出错误,该错误同样会被catch方法捕获。
var promise = new Promise(function(resolve, reject) {
throw new Error('test');
});
promise.catch(function(error) {
console.log(error);
});
// Error: test
③ 以下是两种常见的写法示例。
// 写法一
var promise = new Promise(function(resolve, reject) {
try {
throw new Error('test');
} catch(e) {
reject(e);
}
});
promise.catch(function(error) {
console.log(error);
});
// 写法二
var promise = new Promise(function(resolve, reject) {
reject(new Error('test'));//reject方法的作用,等同于抛出错误
});
promise.catch(function(error) {
console.log(error);
});
④ 需要注意的是,如果在resolve语句之后抛出错误,该错误不会被捕获。这是因为Promise的状态一旦改变,就会永久保持该状态,不再发生任何变化。
var promise = new Promise(function(resolve, reject) {
resolve('ok');
throw new Error('test');
});
promise
.then(function(value) { console.log(value) })
.catch(function(error) { console.log(error) });
// ok
Promise.all并发处理
7. Promise.all()方法
该方法接收一个Promise对象的数组作为参数,将多个Promise实例包装成一个新的Promise对象。如果数组中的元素不是Promise对象,系统会自动调用Promise.resolve方法将其转换为Promise实例,再进行后续处理。(注意:Promise.all方法的参数不一定非要是数组,但必须具有Iterator接口,且返回的每个成员都必须是Promise实例)。
var p = Promise.all(promises).then(function (posts) {
// ...
}).catch(function(reason){
// ...
});
① 只要promises数组中有一个状态变为rejected,新包装的Promise对象p的状态就会变为rejected,此时第一个被reject的实例的返回值会传递给p的回调函数。 ② 如果所有Promise对象都变为resolved,则promises数组中所有对象的返回值会组成一个数组,传递给p的回调函数。
Promise.resolve对象转换
8. Promise.resolve()方法
该方法用于将现有对象转换为Promise对象,其核心作用即为此。
Promise.resolve('foo')
// 等价于
new Promise(resolve => resolve('foo'))
① 如果参数是一个Promise对象,Promise.resolve()将不做任何处理,直接返回该对象。 ② 如果参数是一个具有then方法的对象(即thenable对象),Promise.resolve方法会将其转换为Promise对象,并立即执行该对象的then方法。
let thenable = {
then: function(resolve, reject) {
resolve(42);
}
};
let p1 = Promise.resolve(thenable);//p1为一个状态已经是resolved 的promise对象.
p1.then(function(value) {
console.log(value); // 42
});
③ 如果参数不是具有then方法的对象,或者根本不是对象。
该参数将作为生成的Promise对象的resolve()方法的参数。
var p = Promise.resolve('Hello');//Hello 会传递给 p 的resolve()
p.then(function (s){
console.log(s)
});
// Hello
希望本文的阐述能对大家的ECMAScript程序设计有所帮助。
JS动态构建复杂嵌套JSON对象的方法
2026-11-05 15:41:52
JS负数取余为什么是负数?详解余数与模运算区别
2026-11-05 13:34:41
JS 解压出现乱码或报错怎么解决?
2026-11-05 12:32:38
JS 中 startsWith、indexOf 与正则判断字符串前缀的对比
2026-11-04 22:19:43
JS解析Excel后怎么将数据转换为JSON格式
2026-11-04 20:58:28
