什么是Promise,咱们常把它翻译为期约。
想象一个场景:
咱向你寄一封信,企图索要你的数据,但咱不知道信是否成功送到,或者你是否会给咱数据。
更痛苦的是,咱忙的要命,不可能一直等回信再做后续决策。
更更加痛苦的是,你的数据对咱的工作至关重要,草。
那么要怎么办才能在不影响咱正常工作的情况下,处理好这一切呢?
JS给出的方法是,事先决策好一切,再请一位聪明的邮差帮咱搞定。
咱们可以在寄出信的时候,附上注脚:
- 如果能拿到这些数据,那么把数据加入到工作之中。
- 如果没能拿到数据,那么放弃这部分工作。
这样寄出信后,邮差会根据咱的注脚,来协助完成工作,并且咱正常的工作也不会被打断。
Promise就是这个聪明的邮差
Promise能够接收一个执行函数,这个函数提供两个方法作为参数,一个用于宣告成功,一个用于宣告失败。
来举个代码例子:
js
//giveMeData是向你索要数据的方法,接受一个回调函数作为后续处理,回调函数会接收请求状态
//事先决策好一切,这就是咱们的注脚了
const executor = (resolve, reject) => {
giveMeData((data)=>{
if(data){
console.log('宣告成功!获取到数据了!')
resolve(data)
}
else{
console.log('宣告失败...没有获取到数据,草')
reject()
}
})
}
//把决策交给邮差
const myPostman = new Promise(executor);
这段代码中,咱们声明了一个Promise,用这个Promise去执行giveMeData这段代码。
在代码执行的角度,这意味着
- 咱们通过Promise方法向JS引擎的【异步队列】中推入了一个任务,giveMeData。
- giveMeData这个任务不会阻塞咱们正常的工作,他正在异步地、悄悄地向你发起了请求索要数据。
- ※giveMeData的后续所有操作,都进入了异步队列受到Promise的接管,所以任何同步执行的代码无法访问到giveMeData后续的操作,因为同步执行的代码无法得知这个方法何时宣告成功,就像是你无法得知你寄出的邮件经历了什么一样,只有你那聪明的邮差Promise能够做出后续的处理。
- ※无论结果如何,别忘了让邮差宣告自己是成功了还是失败了,不然你只能亲自去找邮差了。
- 人格
好的,那么这看上去只是咱们把策略传递给了聪明的邮差,让他送了个件,拿到了咱们需要的数据并且告诉了咱们目前的情况。
但是邮差只是个邮差,他无法预料到咱打算何时处理这一堆不明所以数据,所以邮差还是需要咱的一点点指挥。
来看代码:
js
//myWork是执行咱们工作的函数,将数据传入进去开始工作,调用它的abandon方法放弃工作,返回值是工作的执行状态。
const onResolve= (data)=>{
//这个data,就是咱们在宣告成功时传入的参数
//工作开始啦!
const workState = myWork(data)
//返回工作状态,用作后续操作
return(workState)
}
const onReject= ()=>{
//咱们在宣告失败时没有传入参数,所以此时没有接收到参数...
const workState = myWork.abandon()
//返回工作状态,用作后续操作
return(workState)
}
//使用then方法,指挥Promise进行下一步动作
//then方法接收两个方法参数,分别对应宣告成功与宣告失败的后续操作;
//在认为工作能够开始时,指挥一下邮差吧!
const start_myWork = myPostman.then(onResolve,onReject)
好好好,邮差已经接收了你的指挥
- 宣告成功的话咱们的myWork会接收到数据然后运行下去,并且返回工作状态;
- 宣告失败的话那就放弃myWork并且返回工作状态。
好一个聪明的邮差!
咱们得到了这些成果:
- 根据不同的宣言,then能够进入不同的函数
- 在then方法中,接收到了Promise在不同宣言下传递参数。
- 在不同的函数中,得到了对应的返回值(就是那个工作状态)
工作顺利开展了,一切看上去好像风平浪静
但是咱们leader突然打来了一个电话,表示工作出了问题,让咱们看看工作的状态。
发!破事真多!但是别慌,咱们返回了工作状态,来看看怎么个事。
还好有先见之明,咱们在调用 myPostman.then 时声明了一个 start_myWork 来存储它的结果,那么它的结果是什么?
答案是,还是Promise。
请记住,身为一个Promise,无论做了什么,它的返回值只可能是一个Promise。 就像是聪明的邮差即使是听从指示帮咱们做了些工作,也只是尽了邮差的工作,归根结底只是邮差,聪明一点罢了...
等等,他既然还是邮差!那咱们还能用then指挥他吗?
下面是代码:
js
const readWorkState = (state)=>{
//这个state哪来的不必多说了吧...就是咱们之前调用then时的返回值
if(state){
return state.readState;
}
else{
return false;
}
};
//此时咱们的工作正常进行下去了,就不用考虑运行失败的情况
//then方法允许咱们偷一点懒,只关心成功的情况。
//但是没有传入处理失败的函数,万一出了点什么事,就只能用无情的报错来回应你了...
//咱选择偷懒
const myWorkState = start_myWork.then(readWorkState)
//myWorkState获取到了工作的状态!
好了,读取到了状态了,看起来没什么问题。
一定是leader的问题,zzz启动!
别急着启动,至少总结一下吧:
- 任何Promise的返回值都只会是Promise,所以一旦进入异步的操作,后续的操作都是异步了,即所有异步操作的进一步操作都必须通过Promise进行。
希望你能理解 "Promise是JS为异步操作提供的接口对象" 这一句话。
- 对于Promise,then方法是可以链式调用的,也就是
js
Promise.then().then().then()
这样的用法,也称为Promise的Thenable特性。
- then的处理函数中的返回值,会作为之后调用then的对应处理函数的参数,这是Promise的返回值传递特性。
这样,通过聪明的邮差Promise完美解决了异步获取数据并且用于工作这一难题。