优雅的异步编程 Promise详解

Promise是什么?

    Promise是异步编程的一种解决方案,比传统的解决方案--回调函数和事件--更加合理和强大。最早是在社区提出和实现,ES6将其写进了语言标准,统一了语法,原生提供了Promise对象。

    好吧,那Promise到底是什么?嗯。。。。貌似可以提升逼格¥0#¥@

    还是少一点套路直接上例子比较好理解。在敞开心扉之前,先请客官大人记住Promise的2大特性,①Promise的对象状态不受外界影响。②一旦状态改变,就不会再变,任何时候都可以得到这个结果。(试想你的代码中有这么个对你忠贞的姑娘,484灰常激动。)当然,Promise也有一些小缺憾,后文会提到。

    场景1:

        $.ajax({
            ****
            success:dosomething(data){}
        })
这是个最简单的AJAX异步获取数据的场景,一切都显得那么和谐完美无瑕,简直666,
好了,老板说我们的业务变得复杂了 

    场景2:

       $.ajax({
           ****
           success:fn(data){
               $ajax({
               ***
               success:dosomethis(data){
                   ...
                   }
               })
           }
       )}

这个场景描述描述的是一个AJAX请求依赖于另一个AJAX请求成功后获得的返回值,我们写出了两层嵌套的AJAX连环炮,你似乎已经能看到你的未来了,随着我们的业务变的越来越复杂,你的代码可读性会变的越来越差,你的连环炮越打越长,到后面你自己也找不到中间到底哪里会出错,会出什么错。这显然不够优雅~

场景2会轻松形成一个叫回调地狱的场景,可以让你的代码维护者花上一整天来弄懂你的这一些列连环炮到底是做什么的。这似乎是个报仇的好办法。好了,这并不好,作为一名优雅的不行的前端开发工程师,是时候来一波无形装逼了。

Promise基本用法

    var promise = new Promise(function(resolve,reject){
        // ... some code if(/* 异步操作成功 */){
            resolve(value);
        }else{
            reject(error);}
        });

Prominse构造函数接受一个函数作为参数,该函数的两个参数分别是resolvereject。他们是两个函数,由JavaScript引擎提供,不用自己部署。(通俗点讲就是。一个带了两个奇怪的函数作为参数的函数把你的异步代码包裹起来了作为参数给了Promise构造器造了一个Promise实例。优雅么,酸爽么,%……%¥)

那函数里面是什么鬼,回顾刚刚让你特别记住的两点的。就是每个Promise对象都有一个保存保存状态的功能,当Promise实例被创建出来的时候,她有了第一个状态Pending,然后被你包裹的那段异步代码开始执行,&……¥¥#*,如果一切ok,异步操作成功了,执行埋伏已久的resolve函数,并且把需要处理的返回值作为参数传递出去,Promise对象的状态从Pending置成Resolved(又称Fulfilled),要是其中发生了什么乱七八糟牛鬼蛇神的事情导致的异步操作失败了,执行reject函数并将错误信息传递出去,Promise对象的状态就会从Pending置成Rejected,你还需要记住刚刚的第二点,这个状态的改变不可逆且不可重复改变。这就是Promise承若的名字由来吧,多么美丽美好,仿佛看见十八岁的妹子在对你Promise Promise P...。

Promise实例生成以后,可以用then的方法指定Resolved状态和Reject状态的回调函数。先看写法

    promise.then(function(value){
        // success
    },function(error){
       // failure
    });

then方法可以接收两个回调函数作为参数,第一个回调函数是Promise对象的状态变成Resolved时的回调,第二个则是Promise对象的状态变为Rejected时调用。第二个参数是可选的,这两个函数都自动接收Promise对象传出的值作为参数。

说了这么多,我们来看看如何改下我们之前的场景2

首先我们把异步操作都交给Promise去实例一个Promise对象,并且封装到一个方法作为返回值以供链式调用。

function doFir (){
    return new Promise((resolve,reject)=>{
        $.ajax({
            ****
            success:resolve(value)  //成功后改变Promise的状态并且将value交给resolve传递出去
            error:reject(err)  //失败后 将Promise状态Rejected并且将err交给reject传递出去
        })
    })  //整个Promise实例作为返回值返回出去
}

function doSec(value){
    return new Promise((resolve,reject)=>{
        $.ajax({
            ****
            success:resolve(value)  //成功后改变Promise的状态并且将value交给resolve传递出去
            error:reject(err)  //失败后 将Promise状态Rejected并且将err交给reject传递出去
        })
    })  //整个Promise实例作为返回值返回出去
}

function doThi(value){
    return new Promise((resolve,reject)=>{
        $.ajax({
            ****
            success:resolve(value)  //成功后改变Promise的状态并且将value交给resolve传递出去
            error:reject(err)  //失败后 将Promise状态Rejected并且将err交给reject传递出去
        })
    })  //整个Promise实例作为返回值返回出去
}

为了体现Promise的优雅,多加了一个异步操作,注意现在三个任务函数的关系是并列的,他们共享同一个作用域,在作用域链中的位置也是同级的,作用域链不理解的同学跳过没关系。然后开始展现Promise的优雅。bi~~~u~~

doFir().then((value) => {doSec(value)})
           .then((value) => {doThi(value)})

QAQ!~~~好吧我们稍微拆解一下说明其中的那些优雅
doFir()
          .then((value) => {doSec(value)})//这里then省略了第二个参数,也就是Promise为Rejected时候的回调,第一个                                                                //回调函数会接收到success:resolve(value)传递出来的value参数,开始执行                                                                    //doSec()
          .then((value) => {doThi(value)})//因为doSec()返回的是一个新的Promise对象,一样的你可以接着then

至此,一个嵌套的多层级的异步代码块通过使用Promise扁平化了,阅读者和编程者都能快速清晰的知道这一串链式调用到底要做什么。

好吧 优雅的和大家说88~

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

推荐阅读更多精彩内容