2018-6-27 seo达人
如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里
Promise 是异步编程的一种解决方案,比传统的解决方案–回调函数和事件--更合理和更强大。它由社区最早提出和实现,ES6将其写进了语言标准,统一了语法,原生提供了Promise
所谓Promise ,简单说就是一个容器,里面保存着某个未来才回结束的事件(通常是一个异步操作)的结果。从语法上说,Promise是一个对象,从它可以获取异步操作的消息。
三种状态:
状态改变:
这两种情况只要发生,状态就凝固了,不会再变了,这时就称为resolved(已定型
基本用法
ES6规定,Promise对象是一个构造函数,用来生成Promise实例
Promise的源码分析:
曾几何时,我们的代码是这样的,为了拿到回调的结果,不得不
终于,我们的
首先我们要知道自己手写一个
我们先声明一个类,叫做
那么接下来我会分析上面代码的作用,原理
then方法是
这里主要做了将构造器中resolve和reject的结果传入
之前我们只是处理了同步情况下的Promise,简而言之所有操作都没有异步的成分在内。那么如果是异步该怎么办?
最早处理异步的方法就是callback,就相当于我让你帮我扫地,我会在给你发起任务时给你一个手机,之后我做自己的事情去,不用等你,等你扫完地就会打手机给我,诶,我就知道了地扫完了。这个手机就是callback,回调函数。
首先我们需要改一下构造器里的代码,分别添加两个回调函数的数组,分别对应成功回调和失败回调。他们的作用是当成功执行resolve或reject时,执行callback。
然后是then需要多加一个状态判断,当Promise中是异步操作时,需要在我们之前定义的回调函数数组中添加一个回调函数。
ok!大功告成,异步已经解决了
这也是
一下子多了很多方法,不用怕,我会一一解释
那就让我们来看看这个
它的作用是用来将onFufilled的返回值进行判断取值处理,把最后获得的值放入最外面那层的
我们现在已经基本完成了Promise的then方法,那么现在我们需要看看他的其他方法。
相信大家都知道catch这个方法是用来捕获Promise中的reject的值,也就是相当于then方法中的onRejected回调函数,那么问题就解决了。我们来看代码。
该方法是挂在Promise原型上的方法。当我们调用catch传callback的时候,就相当于是调用了then方法。
大家一定都看到过
这两个方法是直接可以通过class调用的,原理就是返回一个内部是resolve或reject的Promise对象。
all方法可以说是Promise中很常用的方法了,它的作用就是将一个数组的Promise对象放在其中,当全部resolve的时候就会执行then方法,当有一个reject的时候就会执行catch,并且他们的结果也是按着数组中的顺序来排放的,那么我们来实现一下。
其原理就是将参数中的数组取出遍历,每当执行成功都会执行
race方法虽然不常用,但是在Promise方法中也是一个能用得上的方法,它的作用是将一个
原理大家应该看懂了,很简单,就是遍历数组执行Promise,如果有一个
语法糖这三个字大家一定很熟悉,作为一个很Swag的前端工程师,对async/await这对兄弟肯定很熟悉,没错他们就是generator的语法糖。而我们这里要讲的语法糖是Promise的。
什么作用呢?看下面代码你就知道了
没错,我们可以方便的去调用他语法糖defer中的
Promise 的含义
Promise 对象的状态不受外界影响
Promise对象的状态改变,只有两种可能:
resolve
函数的作用是,将Promise对象的状态从“未完成”变为“成功”(即从 pending
变为 resolved
),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;
reject
函数的作用是,将Promise对象的状态从“未完成”变为“失败”(即从 pending
变为 rejected
),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
1.回调地狱
callback hell
,这种环环相扣的代码可以说是相当恶心了
盖世英雄
出现了,他身披金甲圣衣、驾着七彩祥云。好吧打岔儿了,没错他就是我们的Promise
,那让我们来看看用了Promise
之后,上面的代码会变成什么样吧
2.重点开始,小眼睛都看过来
2.1 Promise/A+
Promise
,应该怎么去写,谁来告诉我们怎么写,需要遵循什么样的规则。当然这些你都不用担心,其实业界都是通过一个规则指标来生产Promise
的。让我们来看看是什么东西。传送门☞Promise/A+
2.2 constructor
Promise
,里面是构造函数。如果es6还有问题的可以去阮大大的博客上学习一下(传送门☞es6)
executor:
这是实例Promise
对象时在构造器中传入的参数,一般是一个function(resolve,reject){}
status:``Promise
的状态,一开始是默认的pendding状态,每当调用道resolve和reject方法时,就会改变其值,在后面的then方法中会用到
value:
resolve回调成功后,调用resolve方法里面的参数值
reason:
reject回调成功后,调用reject方法里面的参数值
resolve:
声明resolve方法在构造器内,通过传入的executor方法传入其中,用以给使用者回调
reject:
声明reject方法在构造器内,通过传入的executor方法传入其中,用以给使用者回调
2.3 then
Promise
中最为重要的方法,他的用法大家都应该已经知道,就是将Promise
中的resolve或者reject的结果拿到,那么我们就能知道这里的then方法需要两个参数,成功回调和失败回调,上代码!
onFufilled
和onRejected
中,注意这两个是使用者传入的参数,是个方法。所以你以为这么简单就完了?要想更Swag
的应对各种场景,我们必须得再完善。继续往下走!
3.异步的Promise
3.1 callback!!!!
3.2 resolvePromise
Promise
中的重头戏,我来介绍一下,我们在用Promise的时候可能会发现,当then函数中return了一个值,我们可以继续then下去,不过是什么值,都能在下一个then中获取,还有,当我们不在then中放入参数,例:promise.then().then()
,那么其后面的then依旧可以得到之前then返回的值,可能你现在想很迷惑。让我来解开你心中的忧愁,follow me。
Promise
?:首先我们要注意的一点是,then有返回值,then了之后还能在then,那就说明之前的then返回的必然是个Promise
。
setTimeout
?:因为Promise本身是一个异步方法,属于微任务一列,必须得在执行栈执行完了在去取他的值,所以所有的返回值都得包一层异步setTimeout。
resolvePromise
是什么?:这其实是官方Promise/A+的需求。因为你的then可以返回任何职,当然包括Promise
对象,而如果是Promise
对象,我们就需要将他拆解,直到它不是一个Promise
对象,取其中的值。
resolvePromise
到底长啥样。
Promise
的resolve函数中。
promise2
(then函数返回的Promise对象),x
(onFufilled函数的返回值),resolve、reject
(最外层的Promise上的resolve和reject)。
promise2
和x
?:首先在Promise/A+中写了需要判断这两者如果相等,需要抛出异常,我就来解释一下为什么,如果这两者相等,我们可以看下下面的例子,第一次p2是p1.then出来的结果是个Promise
对象,这个Promise
对象在被创建的时候调用了resolvePromise(promise2,x,resolve,reject)函数,又因为x等于其本身,是个Promise
,就需要then方法递归它,直到他不是Promise
对象,但是x(p2)的结果还在等待,他却想执行自己的then方法,就会导致等待。
resolvePromise
函数已经resolve或者reject了,那就不需要在执行下面的resolce或者reject。
resolvePromise
函数?:相信细心的人已经发现了,我这里使用了递归调用法,首先这是Promise/A+中要求的,其次是业务场景的需求,当我们碰到那种Promise的resolve里的Promise的resolve里又包了一个Promise的话,就需要递归取值,直到x不是Promise对象。
4.完善Promise
4.1 catch
4.2 resolve/reject
Promise.resolve()、Promise.reject()
这两种用法,它们的作用其实就是返回一个Promise对象,我们来实现一下。
4.3 all
processData
方法,processData
方法就是用来记录每个Promise的值和它对应的下标,当执行的次数等于数组长度时就会执行resolve,把arr的值给then。这里会有一个坑,如果你是通过arr数组的长度来判断他是否应该resolve的话就会出错,为什么呢?因为js数组的特性,导致如果先出来的是1位置上的值进arr,那么0位置上也会多一个空的值,所以不合理。
4.4 race
Promise
数组放入race中,哪个先执行完,race就直接执行完,并从then中取值。我们来实现一下吧。
Promise
执行成功就resolve。
Promise语法糖 deferred
Promise
对象。那么它还有没有另外的方法呢?答案是有的。我们需要在全局上安装promises-aplus-tests插件npm i promises-aplus-tests -g
,再输入promises-aplus-tests [js文件名] 即可验证你的Promise的规范。
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务
蓝蓝设计的小编 http://www.lanlanwork.com