ES6之Promise的使用
Promise 的基本使用
🔷Promise到底是做什么的呢?
🔹Promise是异步编程的一种解决方案。
🔷那什么时候我们会来处理异步事件呢?
🔹一种很常见的场景应该就是网络请求了。
🔹 我们封装一个网络请求的函数,因为不能立即拿到结果,所以不能像简单的3+4=7一样将结果返回。
🔹所以往往我们会传入另外一个函数,在数据请求成功时,将数据通过传入的函数回调出去。
🔹如果只是一个简单的网络请求,那么这种方案不会给我们带来很大的麻烦。
但是,当网络请求非常复杂时,就会出现回调地狱。
OK,我以一个非常夸张的案例来说明。
🔷我们来考虑下面的场景(有夸张的成分):
🔹我们需要通过一个url1从服务器加载一个数据data1,data1中包含了下一个请求的url2
🔹我们需要通过data1取出url2,从服务器加载数据data2,data2中包含了下一个请求的url3
🔹我们需要通过data2取出url3,从服务器加载数据data3,data3中包含了下一个请求的url4
🔹发送网络请求url4,获取最终的数据data4
🔷上面的代码有什么问题吗?
🔹正常情况下,不会有什么问题,可以正常运行并且获取我们想要的结果。
🔹但是,这样额代码难看而且不容易维护。
🔹我们更加期望的是一种更加优雅的方式来进行这种异步操作。
🔷如何做呢?就是使用Promise。
🔹Promise可以以一种非常优雅的方式来解决这个问题。
我们先来看看Promise最基本的语法。
这里,我们用一个定时器来模拟异步事件:
假设下面的data是从网络上1秒后请求的数据
console.log就是我们的处理方式。
1 | new Promise(function(resolve, reject) { |
一般情况下是有异步操作时,使用Promise对这个异步操作进行封装,
new-> 构造函数(1.保存一些状态信息,2.执行传入的函数)
在执行传入的回调函数的时候,会传入两个参数,resolve,reject,他们本身又是函数,
当请求操作成功的时候,会调用resolve() 函数,拿到请求到的数据会在new Promise 出来的Promise对象的 then 方法中进行操作,then方法的参数又是一个函数。
当请求操作失败的时候,会调用reject() 函数,得到失败的信息,将会被new Promise 出来的Promise对象的 catch 方法捕获。
1 | new Promise(function(resolve, reject) { |
Promise三种状态
🔹pending:等待状态,比如正在进行网络请求,或者定时器没有到时间。
🔹fulfill:满足状态,当我们主动回调了resolve时,就处于该状态,并且会回调.then()
🔹reject:拒绝状态,当我们主动回调了reject时,就处于该状态,并且会回调.catch()
Promise链式调用
无论是then还是catch都可以返回一个Promise对象。所以,我们的代码其实是可以进行链式调用的:
这里我们直接通过Promise包装了一下新的数据,将Promise对象返回了
Promise.resovle():将数据包装成Promise对象,并且在内部回调resolve()函数
Promise.reject():将数据包装成Promise对象,并且在内部回调reject()函数
链式调用简写
简化版代码:
如果我们希望数据直接包装成Promise.resolve,那么在then中可以直接返回数据
注意下面的代码中,我讲return Promise.resovle(data)改成了return data。结果依然是一样的
Promise.prototype.then()
Promise实例具有then方法,也就是说then方法时定义在原型对象上的。
它的作用是为Promise实例添加状态改变时的回调函数。
前面说过,then方法的第一个参数是resolved状态的回调函数,第二个参数是rejected状态的回调函数(可选)。
then方法返回的是一个新的Promise实例(注意,不是原来那个Promise实例)因此可以采用链式写法,即then方法后面再调用另一个then方法。
采用链式的then可以指定一组按照次序调用的回调函数。这时,前一个回调函数可能返回一个还是Promise对象(即有异步操作),这时候一个回调函数就会等该Promise对象的状态发生变化,才会被调用。
Promise.prototype.catch()
Promise.prototype.catch方法是.then(null, rejection)的别名,用于指定发生错误时的回调函数。
1 | new Promise(function(resolve, reject) { |
Promise.all()
Promise.all(iterable) 方法返回一个 Promise 实例,此实例在 iterable 参数内所有的 promise 都“完成(resolved)”或参数中不包含 promise 时回调完成(resolve);如果参数中 promise 有一个失败(rejected),此实例回调失败(reject),失败原因的是第一个失败 promise 的结果。
当我们又这样的一个需求的时候:我们需要发两次请求或者多次请求,我们需要等这些请求都完成之后,再进行一个需求操作。那么这个时候我们如何来实现的?我们就可以使用 Promise.all() 。
我们这里还是使用 setTimeout() 来模拟请求。
1 | Promise.all([ |
当网络请求都完成的时候,就会执行 Promise.all() 的then方法。网络请求的数据都会放在 results 数组中。然后我们就可以对其进行操作。
需要特别注意的是,Promise.all获得的成功结果的数组里面的数据顺序和Promise.all接收到的数组顺序是一致的,即请求1的结果在前,即便请求1的结果获取的比请求2要晚。
Promise.race的使用
Promise.race(iterable) 方法返回一个 promise,一旦迭代器中的某个promise解决或拒绝,返回的 promise就会解决或拒绝。
顾名思义,Promse.race就是赛跑的意思,意思就是说,Promise.race([p1, p2, p3])里面哪个结果获得的快,就返回那个结果,不管结果本身是成功状态还是失败状态。
1 | Promise.race([ |
Use this card to join the candyhome and participate in a pleasant discussion together .
Welcome to aqing's candyhome,wish you a nice day .