难点图解:then()方法
ES6学习网站:ES6 入门教程
解决:回调地狱(回调函数中嵌套回调)
两个特点:
(1)对象的状态不受外界影响。Promise
对象代表一个异步操作,有三种状态:pending
(进行中)、fulfilled
(已成功)和rejected
(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。
(2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise
对象的状态改变,只有两种可能:从pending
变为fulfilled
和从pending
变为rejected
。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。如果改变已经发生了,你再对Promise
对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。
实现Promise
手写实现一个基本的 Promise
涉及到几个核心部分:状态管理(pending, fulfilled, rejected)、then 方法实现(支持链式调用)、catch 方法实现(错误处理)、以及 finally 方法的可选实现。下面是一个简化版的 Promise
实现:
function Promise(executor) {
if (typeof executor !== 'function') {
throw new TypeError('Promise resolver undefined is not a function');
}
// Promise 的三种状态
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
let status = PENDING;
let value = undefined;
let reason = undefined;
// 存储成功和失败的回调
const onFulfilledCallbacks = [];
const onRejectedCallbacks = [];
function resolve(newValue) {
if (status === PENDING) {
// 新的值需要是Promise,则递归解析
if (newValue instanceof Promise) {
return newValue.then(resolve, reject);
}
status = FULFILLED;
value = newValue;
// 异步执行所有成功回调
onFulfilledCallbacks.forEach(fn => fn());
}
}
function reject(newReason) {
if (status === PENDING) {
status = REJECTED;
reason = newReason;
// 异步执行所有失败回调
onRejectedCallbacks.forEach(fn => fn());
}
}
// 捕获执行器抛出的错误
try {
executor(resolve, reject);
} catch (e) {
reject(e);
}
// then 方法
this.then = function(onFulfilled, onRejected) {
return new Promise((resolve, reject) => {
// 处理成功情况
function handleOnFulfilled() {
try {
if (typeof onFulfilled === 'function') {
const result = onFulfilled(value);
// 如果结果是Promise,则继续等待,否则直接解析
if (result instanceof Promise) {
result.then(resolve, reject);
} else {
resolve(result);
}
} else {
resolve(value);
}
} catch (e) {
reject(e);
}
}
// 处理失败情况
function handleOnRejected() {
try {
if (typeof onRejected === 'function') {
const result = onRejected(reason);
if (result instanceof Promise) {
result.then(resolve, reject);
} else {
resolve(result);
}
} else {
reject(reason);
}
} catch (e) {
reject(e);
}
}
// 根据当前Promise的状态决定是执行成功回调还是失败回调
if (status === FULFILLED) {
setTimeout(handleOnFulfilled);
} else if (status === REJECTED) {
setTimeout(handleOnRejected);
} else {
// 如果状态还未确定,则添加到对应的回调数组中
onFulfilledCallbacks.push(handleOnFulfilled);
onRejectedCallbacks.push(handleOnRejected);
}
});
};
// catch 方法
this.catch = function(onRejected) {
return this.then(null, onRejected);
};
// finally 方法(可选实现)
this.finally = function(onFinally) {
return this.then(
value => Promise.resolve(onFinally()).then(() => value),
reason => Promise.resolve(onFinally()).then(() => { throw reason; })
);
};
}
// 示例用法
new Promise((resolve, reject) => {
setTimeout(() => resolve('hello'), 1000);
}).then(data => {
console.log(data); // 输出: hello
return 'world';
}).then(data => {
console.log(data); // 输出: world
}).catch(error => {
console.error(error);
});
创建 Promise
你可以使用 new Promise()
构造函数来创建一个 Promise。它接受一个带有 resolve
和 reject
两个参数的函数,这个函数会在异步操作完成(成功或失败)时被调用。
let myPromise = new Promise((resolve, reject) => {
// 异步操作
setTimeout(() => {
let success = true;
if (success) {
resolve("操作成功!"); // 成功时调用 resolve,状态fulfill且改变当前promise对象的结果
} else {
reject("操作失败!"); // 失败时调用 reject
}
}, 2000); // 模拟2秒延迟
});
Promise原型的方法
then()
p.then(value)=>{console.log('value')},成功调用时执行,resolve()类似声明,将形参传给then()方法
在then()方法的参数函数中,通过形参使用promise对象的结果
如果promise的状态不改变,then()里的方法不会执行
使用return会将当前promise实例的状态改成fulfilled,return返回值将作为形参传给下一个then()
如果当前then()中代码出错,会将promise实例的状态改成rejected
catch()
catch(),失败调用时执行
何时触发?reject()或者Promise执行体中有错
处理 Promise
使用 then()
方法来处理 Promise 对象的成功完成情况,并使用 catch()
方法来处理失败情况。
myPromise.then((message) => {
console.log("成功:", message); // Promise 被 resolve 时执行
}).catch((error) => {
console.error("错误:", error); // Promise 被 reject 时执行
});
上边说到Promise是一个构造函数,new之后等于说调用了构造函数,构造函数中传的参数是一个函数,这个函数内的两个参数分别又是两个函数(
reslove
和reject
)
Promise 链
Promise 可以通过链式调用进一步简化处理多个异步操作的代码。在 then()
方法中返回一个新的 Promise对象,状态为pending,可以使得链式调用变得更加清晰。
// 假设有一个函数 fetchUserData 返回一个 Promise,用于获取用户数据
fetchUserData()
.then((userData) => {
// 处理获取到的用户数据
return fetchUserPosts(userData.userId); // 返回另一个 Promise
})
.then((userPosts) => {
// 处理获取到的用户发帖数据
})
.catch((error) => {
console.error("处理过程中出现错误:", error);
});
Promise.all
Promise.all()
用于同时处理多个 Promise,并在所有 Promise 都成功时返回一个包含所有结果的 Promise,但只要有一个 Promise 失败,它就会立即返回失败。
let promise1 = someAsyncOperation();
let promise2 = anotherAsyncOperation();Promise.all([promise1, promise2])
.then((results) => {
// results 包含了两个 Promise 的结果
})
.catch((error) => {
// 处理失败情况
});
Promise.race
Promise.race()
用于竞争多个 Promise,返回一个新的 Promise,其结果由最先完成的 Promise 决定
let promise1 = fetchUserData();
let promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
reject("操作超时!");
}, 500); // 模拟超时操作
});Promise.race([promise1, promise2])
.then((result) => {
// 处理最先完成的 Promise 的结果
})
.catch((error) => {
// 处理失败情况,可能是超时或其他原因
});