前言
JavaScript是一门单线程语言,这就意味着它一次只能按顺序执行一段代码。然而,在我们实际web开发应用中,总有一些耗费时间和性能的任务,而为了不阻塞主线程的进行,异步操作就诞生了(如网络请求,读写文件,定时器等),它允许我们等待一个异步操作完成时继续进行下面的任务。在es6之前,开发者主要依赖回调函数来管理异步函数逻辑,但这种方式容易导致“回调地狱”,即嵌套多层回调函数,使得代码难以阅读和维护。
为了解决这些问题,JS在es6中引入了
Promise
对象,它提供了一种更优雅的方式来处理异步任务,使得异步执行的顺序可控,并且让异步代码看起来更像是同步代码,提高了代码的可读性和可维护性。
Promise
Promise
通过构造函数new Promise()
创建,构造函数会接收一个执行器(executor),里面装的是耗时性的内容,执行器会在Promise
对象实例化时立即执行。
const p = new Promise(() => {
console.log('a'); // 同步任务
setTimeout(() => {
console.log('b');
}, 1000);
})
// 先输出a,再输出b
Promise
的执行器函数中会接受两个参数,分别是:resolve
和reject
,它们是用于改变Promise
状态的函数。
const p = new Promise((resolve,reject) => {
})
Promise
具有3种状态,分别是pending
,fulfilled
,rejected
。
在Promise
刚被创建时,它便为pending
状态,可以看成是等待状态,它在等待异步操作的完成,只有当异步操作完成,并且调用resolve
或者reject
时才会发生改变。 它们可以通过改变Promise
的状态后通过调用.then()
和.catch()
函数来优雅的处理异步的结果,并且可以捕获和处理可能出现的错误。
const p = new Promise(() => {
console.log('a');
setTimeout(() => {
console.log('b');
}, 1000);
})
console.log(p);
在这个例子中,我们是先打印的p
再执行的异步操作,所以它会返回pending
。
const p = new Promise(() => {
console.log('a');
setTimeout(() => {
console.log('b');
}, 1000);
})
setTimeout(() => {
console.log(p);
},2000);
在这个例子中,我们虽然完成了异步,但是并没有调用resolve
和reject
改变状态,所以返回的还是pending
。
resolve(value)
:用于将Promise
的状态从pending
变为fulfilled
表示异步操作成功完成。resolve
中接受的一个参数value
这个参数可以是任何类型的值,这个值会传递给then
回调函数的第一个参数。如果resolve
没有传递任何参数那么Promise
的状态仍然会是fulfilled
但是其值PromiseResult
会为undefined
。
.then(onFulfilled, onRejected)
:其中有两个函数作为参数,第一个参数为Promise
状态变为fulfilled
时调用的回调函数,第二个则是变为rejected
时调用的回调函数(可选)。你可以通过resolve
传递参数给这两个回调函数来传递值和传递错误的原因。
const p = new Promise((resolve, reject) => {
console.log('a');
setTimeout(() => {
console.log('b');
resolve();
}, 1000);
})
console.log(p);
p.then(() => {
console.log('c');
console.log(p);
})
如果我们此时在控制台打印输出,那么我们只能看到Promise{ undefined }
所以我们要去浏览器中查看。
此时没有传入值,当我们为resolve
传入值后,并且在.then()
中传入后:
const p = new Promise((resolve, reject) => {
console.log('a');
setTimeout(() => {
console.log('b');
resolve('baby');
}, 1000);
})
console.log(p);
p.then((data) => {
console.log(data);
console.log(p);
})
reject(reason)
:用于将Promise
的状态从pending
变为rejected
表示异步操作成功失败。reject
中接受的一个参数reason
这个参数通常是一个错误对象或者字符串,表示失败的原因,这个值会传递给catch
或 then
回调函数的第二个参数。
.catch(onRejected)
:其中有一个函数参数,用来接受失败时传递的错误原因,你可以通过reject
传递参数给它传递错误的原因。
const p = new Promise((resolve, reject) => {
console.log('a');
setTimeout(() => {
console.log('b');
reject('呜呜呜');
}, 1000);
})
console.log(p);
p.catch((error) => {
console.log(error);
console.log(p);
})
Promise
只能从pending
到fulfilled
或者rejected
,并且一旦状态改变后,就不会再改变,且不可逆。