📕重学JavaScript:Promise 的状态和语法
嗨,大家好!这里是道长王jj~ 🎩🧙♂️
有些操作不是我们自己做的,而是让环境或者外面的 JavaScript 帮我们做的。👥
这样的操作叫做异步操作,就像是我们给别人打电话,让他们帮我们办事一样。📞
但是,我们不知道别人什么时候会接电话,什么时候会办完事,所以我们不能用回调、JavaScript 或者我们的代码去跟他们说话或者检查他们的进度。🙅♂️
我们只能做的是把我们想要他们办完事后告诉我们的话或者做的事写在一个回调处理程序里,然后把它给他们,让他们在办完事后打电话回来告诉我们或者帮我们做事。🙆♂️
❓什么是 Promise?
Promise 是一种特殊的 JS 对象,它可以让我们更方便地处理异步操作。异步操作就是那些不会立刻得到结果的操作,比如从网上下载一张图片或者查询一个数据库。Promise 对象就像是一个承诺,它告诉我们,不管异步操作什么时候完成,它都会把结果给我们。👍
Promise 对象的好处是,我们可以像使用普通的 JS 对象一样使用它。我们不用等待异步操作完成,就可以写代码和 Promise 对象交流。这样就可以让我们的代码更简洁、更清晰、更容易理解。👏
Promise 就像是给了异步操作一种神奇的力量,让它们可以和同步操作一样快速和顺畅。🚀
🚩Promise 状态
Promise 对象可以反映异步操作的结果,所以它们有 3 种可能的状态:
- pending - 异步操作还没结束,Promise 对象还在等待。
- fulfilled - 异步操作成功了,Promise 对象给了我们一个满意的结果。😊
- rejected - 异步操作失败了,Promise 对象给了我们一个错误的原因。😢
有时候,我们也会说 Promise 对象已经解决了。这并不是 Promise 对象的状态,而是一种简单的说法,意思是 Promise 对象不再是 pending 状态,而是变成了 fulfilled 或 rejected 状态。这样我们就知道异步操作已经结束,不用再等待了。👌
🚩创建一个 Promise
我们可以用 Promise()
这个函数来制作 Promise 对象。这个函数需要一个参数,就是一个叫做执行器函数的函数。执行器函数里面有两个函数,我们一般叫它们 resolve()
和 reject()
,但是你也可以给它们起别的名字。
var executor = ( resolve, reject ) => {
};
var promise = new Promise( executor );
console.log( promise );
// Promise { <state>: 'pending' }
这段代码就做了一个 Promise 对象,它的状态是 pending
,也就是还在等待异步操作的结果。🤔
📌Resolve
执行器函数里面有启动异步操作的代码。如果异步操作成功了,我们就用 resolve()
这个函数来告诉 Promise 对象,它的状态要变成 fulfilled
。
var promise = new Promise( (resolve, reject) => {
setTimeout(() => {
resolve();
console.log( promise );
}, 1000);
});
// Promise { <state>: "fulfilled", <value>: undefined }
这个例子里,我们用 setTimeout()
这个函数来做一个异步操作。它会等待一秒钟,然后用 resolve()
这个函数来说,异步操作结束了,Promise 对象可以变成 fulfilled
了。这样,当我们用 console.log()
打印 Promise 对象的时候,就可以看到它的状态是 fulfilled
了。👍
Promise 对象在变成 fulfilled
的时候,也会有一个值。这个值就是异步操作的结果。我们没有给 resolve()
这个函数传任何值,所以 Promise 对象的值是 undefined
。如果我们给 resolve()
这个函数传一个值,比如一个字符串,那么 Promise 对象的值就会是那个字符串。
var promise = new Promise( (resolve, reject) => {
setTimeout(() => {
resolve( "我解决了!" );
console.log( promise );
}, 1000);
});
// Promise { <state>: "fulfilled", <value>: "我解决了!" }
📌Reject
如果异步操作没有成功,我们就用 reject()
这个函数来告诉 Promise 对象,它的状态要变成 rejected
。reject()
这个函数也可以传一个值,就是异步操作失败的原因。如果我们不传这个值,那么 Promise 对象的原因就会是 undefined
。
var promise = new Promise( (resolve, reject) => {
setTimeout(() => {
reject();
console.log( promise );
}, 1000);
});
// Promise { <state>: "rejected", <reason>: undefined }
// Uncaught (in promise) undefined
如果我们传了一个值给 reject()
这个函数,比如一个字符串,那么 Promise 对象的原因就会是那个字符串。
var promise = new Promise( (resolve, reject) => {
setTimeout(() => {
reject( "错误了" );
console.log( promise );
}, 1000);
});
// Promise { <state>: "rejected", <reason>: "错误了" }
// Uncaught (in promise) 错误了
其实,我们不用自己定义
resolve()
和reject()
这两个函数。Promise 对象会自动帮我们做好这些。我们只要在执行器函数里面用它们就可以了。你可以这样想,Promise 对象知道它要怎么处理异步操作的结果,所以它知道你用resolve()
或reject()
的时候要做什么。但是它不知道异步操作什么时候结束,也不知道怎么判断异步操作是成功还是失败。所以,我们要用resolve()
和reject()
来告诉它这些信息。🙋♂️
🚩状态改变是单向的
Promise 对象一旦从 pending
状态变成了 fulfilled
或 rejected
,它就不会再变回去了。
它就像是一个定格的画面,永远不会改变。🖼️
fulfilled
的 Promise 对象也不会变成 rejected
的,反过来也一样。
fulfilled
的 Promise 对象也不会再给我们别的结果, rejected
的 Promise 对象也不会再给我们别的原因。
这样就保证了我们的程序只会针对异步操作成功或失败的情况执行一次代码,而不会混乱或重复。
这些是用回调函数做不到的,因为回调函数是我们传给别人的参数,我们不能控制别人怎么用它们。
现在我们知道了怎么用 Promise()
这个函数来做 Promise 对象,以及 Promise 对象怎么从一个状态变成另一个状态。
但是在真正的 Web 开发中,我们更多的时候是用别人已经做好的 Promise 对象,比如 Web API 或第三方库提供的。
Promise()
这个函数主要是用来把一些没有用 Promise 对象的旧的 API(比如我们之前用的 setTimeout()
)包装一下,让它们也能返回 Promise 对象。🎁
🎉 你觉得怎么样?这篇文章可以给你带来帮助吗?当你处于这个阶段时,你发现什么对你帮助最大?如果你有任何疑问或者想进一步讨论相关话题,请随时发表评论分享您的想法,让其他人从中受益。🚀✨