趣味探索promise的秘密

网上也有很多关于promise的讲解,但感觉都停留在理论层面,对于读者来说,看了一遍,似乎已经全部明白了,但真要用起来,发现还是无从下手。因此,本文旨在用人话为小伙伴们解释一下promise到底真正怎么用。
最近的项目里包含了大量的表单交互,必然免不了各种异步请求,promise使用相当频繁。我想,是时候来与小伙伴们分享一下我遇到的各种promise的坑了。

promise干嘛用的?----一般用于异步操作。
为什么能用来异步操作?----因为能等一个函数执行完之后执行下一个函数操作。
懂了吗?----懂了
那好,用一个我看看----额,那个。。到底怎么写来着。。
你不是都懂了吗?----是啊,道理我都懂啊,但为什么就是不会用呢。。

哈哈,这就是我最初使用promise的深刻感受,明明那些概念都懂,语法也并不复杂,可就是实际用的时候用不出来。如果你也有这种感受,那么,恭喜你,来对地方了,跟着我继续探索promise的秘密吧!

promise和then的配套使用

我们来想象这么一个生活情境:

开学了,幼儿园里的小朋友们排排坐,老师说:小朋友们,让我们来介绍自己的名字好不好呀,那么,从第一排的小红开始,依次往下介绍,好,我们开始吧!
小红站起来说,大家好,我叫小红,
接着小强站起来说,大家好,我叫小强


接着,轮到小明了,小明有个缺点,就是一紧张就口吃,只听他红着脸,站起来说:大。。大。。大。。大。。家。。好。。好。。
还没说完呢,后面的急性子小刚就站了起来,说:大家好,我叫小刚
说完,小刚后面的同学就接着站了起来,继续介绍自己。
最后,最后一排的同学也介绍完自己,坐下去了。此时,到家听到小明的声音:我叫。。叫。。叫。。。叫。。叫。。
此时,老师也不耐烦了,说:行了,小明,坐下吧
可怜的小明,就这样,连一个自我介绍都没有完成。。。

好了,亲,记住上面的故事了吗?我们开始学习promise。本来大家都好好的,按顺序自我介绍,挺好。但毕竟人生不如意十之八九,谁能想到小明有些口吃呢,所以小刚就抢着自我介绍了,你可能想说,这都怪小刚,可人家小刚还委屈呢,老师说的,按照座位来的,既然小明已经开始自我介绍了,那我就开始嘛,谁知道他这么慢呢。
对,小明就是这个异步操作,异步请求和接受服务器相应都是需要时间的,但是人家正常的js程序不管这些,一条语句执行了,下一条语句就会接着执行,不会去管上一条语句又没有完成,程序员你也没说要必须等上一条语句执行完才能执行下一条啊。
这样的问题在哪里呢,问题在最后,老师统计班上同学姓名的时候,会直接把小明漏掉,因为统计的时候,他都没有自我介绍完啊!也就是说,你后面的语句需要用到前面异步的返回值的时候,就会接收不到!
故事还没完呢,接下来听第二段:

第二年,小明班上换了一个班主任,这回小明学聪明了,提前就跟老师说明了他的情况,于是老师想了个办法。
老师说,同学们,我们今年的自我介绍,换一种方式,每一位同学在自我介绍之前,必须要先说出前一位同学的名字,才能进行自我介绍,这样小刚就算再性急,也必须要等小明自我介绍完了才能开始自我介绍。
多么聪明的老师啊,这样,任何同学,都能做完一个完整的自我介绍了!

老师的做法,就是promise。后一个同学必须要等钱一个同学说完,因为他需要前一个同学的名字。来看promise的语法:

new Promise((resolve,reject)=>{
// dosomething(异步操作);
    resolve(value)
})

把老师的做法翻译成js语句就是这样:

var m=new Promise((resolve,reject)=>{
    console.log('小明开始自我介绍')
    setTimeout(()=>{//用定时器模拟的异步操作(小明口吃)
        var name='小明'
        resolve(name)
    },3000)
})
m.then(model=>{
    var preName=model
    var name='小刚'
    console.log(preName)
    console.log(name)
})

执行结果如下:

QQ截图20170208152427.jpg

你会发现,不光是小明在等待了3秒后才打印出来,小刚也一样是等待了3秒后才打印出来,这充分说明了promise的特点,同时我都不用再解释,相信then的用法相信小伙伴们也能很轻易的学会了!

Promise.all的应用场合

接下来,说说Promise.all的应用场合,同样,上故事:

开学第二天,老师需要统计学生们的个人信息,于是让班长小红给每人发了一张个人信息表,让他们填写,并嘱咐她,一定要等所有的同学都填完了,再收上来。小红心里偷偷的笑了,肯定老师已经知道小华写字特别慢了。。

天啊,这到底是怎样一个班级,口吃的、写字慢的。。。为老师默哀一秒钟。。。
咳咳,说正事。其实老师的嘱咐,便是Promise.all的做法,Promise.all语法如下:

Promise.all(arr)

arr是一个包含Promise对象元素的数组,可能这么说还是有点抽象,那接下来把老师的做法翻译成js:

var xiaoming=new Promise((resolve,reject)=>{
    setTimeout(()=>{
        var info={name:'xiaoming',age:'5'}
        resolve(info)
    },2000)
})
var xiaogang=new Promise((resolve,reject)=>{
    setTimeout(()=>{
        var info={name:'xiaogang',age:'6'}
        resolve(info)
    },1000)
})
var xiaohua=new Promise((resolve,reject)=>{
    setTimeout(()=>{
        var info={name:'xiaohua',age:'7'}
        resolve(info)
    },5000)
})
var arr=[xiaoming,xiaogang,xiaohua]
Promise.all(arr).then(model=>{
    console.log(model)
})

结果如你所料,在等待了5秒后,控制台打印出了三个人的信息:

QQ截图20170208154348.png

Promise.all的用法也就一目了然了,它会让多个互不影响的Promise里的语句同时执行,等待所有的Promise语句全部执行完,然后执行then里的操作,返回给then的model是所有Promise里的resolve的值组成的一个数组。

promise的异常处理

同志们,接下来,嘿嘿嘿,继续讲故事:

在填写个人信息的时候,小智的通知看到他填的年龄是8岁,于是指着他说:哈哈哈,你个智障,8岁还读幼儿园。。。小智恼羞成怒,和同桌大打了一架,打架中途,个人信息表也被同桌给撕了。这下子,班长小红苦恼了,老师可是说,要等每个人都写完再把他们所有的信息表收上来,这可怎么办啊。。。

好了,我们暂且先不要管这个班里为什么会有这么多奇葩。我们来看逻辑,本来异步请求正常执行完,接下来就执行then里的resolve,那现在如果向服务器请求失败了,又会怎么样呢,总不能还是执行吧,直接看代码:

var xiaozhi=new Promise((resolve,reject)=>{
    setTimeout(()=>{
        var info={name:'xiaozhi',age:'8'}
        var reason='打架,小智的信息表被撕了'
        if(reason){
            info=null
            reject(reason) 
        }else{
            resolve(info)
        }
        
    },5000)
})
xiaozhi.then(model=>{
    console.log(model)
},error=>{
    console.log('提交个人信息表失败')
    console.log('原因是'+error)
})

这段代码执行结果如下:

Paste_Image.png

小智因为这个事情,被老师狠狠的批评了一顿,他不禁想,如果时光能够倒流,当初没有打这个架该多好啊。小伙伴们,你应该明白我的意思了,不打架,reason就是undefined,就会进入else里的语句,就能正常的输出给then的model了。实际情况正是如此,你很难保证你的请求就一定能够成功响应,如果没有成功请求到数据,你就应该拦住它,执行请求失败的情况的语句。
可能有的小伙伴会错误的理解为,失败那不就是语句执行错误吗?这里一定要主要,这里的失败是指异步请求的失败,并不是js语句的执行失败。换句话说,这里的失败,是你自己定义的失败,如果你非要把请求成功定义为失败,那也会照样进入reject,而不会执行resolve。

Promise.all的异常处理

Promise.all的异常处理是什么样子呢,看代码:

var xiaoming=new Promise((resolve,reject)=>{
    setTimeout(()=>{
        var info={name:'xiaoming',age:'5'}
        resolve(info)
    },2000)
})
var xiaogang=new Promise((resolve,reject)=>{
    setTimeout(()=>{
        var info={name:'xiaogang',age:'6'}
        resolve(info)
    },1000)
})
var xiaohua=new Promise((resolve,reject)=>{
    setTimeout(()=>{
        var info={name:'xiaohua',age:'7'}
        resolve(info)
    },5000)
})
var xiaozhi=new Promise((resolve,reject)=>{
    setTimeout(()=>{
        var info={name:'xiaozhi',age:'8'}
        var reason='打架,小智的信息表被撕了'
        if(reason){
            info=null
            reject(reason) 
        }else{
            resolve(info)
        }
    },1000)
})

var arr=[xiaoming,xiaogang,xiaohua,xiaozhi]
Promise.all(arr).then(model=>{
    console.log(model)
},error=>{
    console.log('收上来失败')
})

执行结果如下:

Paste_Image.png

1秒的时候,打印出“收上来失败”这句话,就好比

小红把除了小智的其他人的信息表全部收上来了给老师,老师一看,少了小智的,说:少了小智的,重新发下去吧,这信息表不全,收上来我也不要。

看到了吧,Promise.all就是保证所有的Promise都是成功的,只要有一个失败,它就执行reject,并且其他的哪怕是成功的Promise结果也都全部舍弃。这叫,一个都不能少!

怎么样,小伙伴们,看了这篇文章,是否如同剥开了Promise身上的那层薄纱,将她看了个仔细呢(咳咳,别想歪。。。)。

如果觉得文章不错,请在下方点赞支持我哦!

参考资料

MDN官方文档--Promise

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 224,619评论 6 522
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 96,163评论 3 402
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 171,789评论 0 366
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 60,911评论 1 300
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 69,920评论 6 399
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 53,410评论 1 314
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 41,788评论 3 428
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 40,762评论 0 279
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 47,293评论 1 324
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 39,328评论 3 345
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 41,456评论 1 354
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 37,063评论 5 350
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 42,775评论 3 337
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 33,231评论 0 25
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 34,363评论 1 275
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 49,995评论 3 381
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 46,519评论 2 365

推荐阅读更多精彩内容