什么是Promise?
Promise是JavaScript中处理异步操作的一种对象。它代表一个异步操作的最终完成(或失败)及其结果值。Promise提供了一种更优雅的方式来处理异步代码,避免了回调地狱。
Promise的基本使用
Promise有三种状态:pending(待定)、fulfilled(已成功)和rejected(已失败)。一旦状态改变,就不会再变。Promise对象可以接受两个参数作为回调函数:resolve和reject。
// www.javascriptcn.com code example
const myPromise = new Promise((resolve, reject) => {
// 异步操作
setTimeout(() => {
const success = true; // 模拟异步操作的结果
if (success) {
resolve("操作成功");
} else {
reject("操作失败");
}
}, 2000);
});
myPromise.then(result => {
console.log(result); // 输出: 操作成功
}).catch(error => {
console.error(error); // 如果异步操作失败,输出: 操作失败
});Promise的方法
Promise对象提供了多个方法来处理异步操作:
then(onFulfilled, onRejected):用于指定操作成功的回调函数onFulfilled和操作失败的回调函数onRejected。catch(onRejected):相当于.then(null, onRejected),用于捕获并处理Promise链中的错误。finally(callback):无论Promise的状态如何,都会执行这个回调函数。通常用来清理资源。
// www.javascriptcn.com code example
myPromise
.then(result => {
console.log(result);
return "处理后的结果";
})
.catch(error => {
console.error(error);
})
.finally(() => {
console.log("无论成功还是失败,我都会被执行");
});Promise链式调用
Promise的一个重要特性是可以进行链式调用。每个then方法返回一个新的Promise对象,这样可以在一个Promise链中连续调用多个异步操作。
// www.javascriptcn.com code example
myPromise
.then(result => {
console.log(result);
return "处理后的结果";
})
.then(newResult => {
console.log(newResult);
return "再次处理后的结果";
})
.then(finalResult => {
console.log(finalResult);
})
.catch(error => {
console.error(error);
});Promise.all和Promise.race
Promise.all(iterable):接收一个Promise数组作为参数,当所有的Promise都变为fulfilled状态时,返回一个新的Promise,其结果是一个包含所有Promise结果的数组;如果任何一个Promise变为rejected状态,则新的Promise立即变为rejected状态。Promise.race(iterable):接收一个Promise数组作为参数,返回一个新的Promise,其结果为数组中第一个完成的Promise的结果。
// www.javascriptcn.com code example
const promise1 = Promise.resolve("第一个Promise");
const promise2 = new Promise((resolve, reject) => {
setTimeout(resolve, 1000, "第二个Promise");
});
const promise3 = new Promise((resolve, reject) => {
setTimeout(reject, 500, "第三个Promise失败");
});
Promise.all([promise1, promise2, promise3])
.then(results => {
console.log(results); // ["第一个Promise", "第二个Promise"]
})
.catch(error => {
console.error(error); // ["第三个Promise失败"]
});
Promise.race([promise1, promise2, promise3])
.then(result => {
console.log(result); // "第一个Promise"
})
.catch(error => {
console.error(error); // 不会执行
});使用Promise实现异步加载图片
下面是一个使用Promise实现图片异步加载的例子:
// www.javascriptcn.com code example
function loadImageAsync(url) {
return new Promise((resolve, reject) => {
const image = new Image();
image.onload = () => {
resolve(image);
};
image.onerror = () => {
reject(new Error(`无法加载图片 ${url}`));
};
image.src = url;
});
}
loadImageAsync('https://example.com/image.jpg')
.then(image => {
document.body.appendChild(image);
})
.catch(error => {
console.error(error);
});Promise的Polyfill实现
由于某些旧浏览器可能不支持原生Promise,我们可以使用polyfill来实现兼容性。
// www.javascriptcn.com code example
(function(global) {
function Promise(executor) {
this.state = 'pending';
this.value = undefined;
this.reason = undefined;
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];
const resolve = value => {
if (this.state === 'pending') {
this.state = 'fulfilled';
this.value = value;
this.onFulfilledCallbacks.forEach(fn => fn());
}
};
const reject = reason => {
if (this.state === 'pending') {
this.state = 'rejected';
this.reason = reason;
this.onRejectedCallbacks.forEach(fn => fn());
}
};
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
Promise.prototype.then = function(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
onRejected = typeof onRejected === 'function' ? onRejected : error => { throw error; };
const promise2 = new Promise((resolve, reject) => {
if (this.state === 'fulfilled') {
setTimeout(() => {
try {
const x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
}
if (this.state === 'rejected') {
setTimeout(() => {
try {
const x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
}
if (this.state === 'pending') {
this.onFulfilledCallbacks.push(() => {
setTimeout(() => {
try {
const x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
});
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
const x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
});
}
});
return promise2;
};
function resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
return reject(new TypeError('循环引用'));
}
let called;
if (x != null && (typeof x === 'object' || typeof x === 'function')) {
try {
const then = x.then;
if (typeof then === 'function') {
then.call(x, y => {
if (called) return;
called = true;
resolvePromise(promise2, y, resolve, reject);
}, err => {
if (called) return;
called = true;
reject(err);
});
} else {
resolve(x);
}
} catch (error) {
if (called) return;
called = true;
reject(error);
}
} else {
resolve(x);
}
}
global.Promise = Promise;
})(window);通过以上介绍,我们了解了Promise的基础概念、基本使用方法、链式调用、常见的Promise方法,以及如何实现一个简单的Promise polyfill。希望这些内容对你理解和使用Promise有所帮助。