• 【JS】302- 回调地狱解决方案之Promise



    为什么出现Promise

    在javascript开发过程中,代码是单线程执行的,同步操作,彼此之间不会等待,这可以说是它的优势,但是也有它的弊端,如一些网络操作,浏览器事件,文件等操作等,都必须异步执行,针对这些情况,起初的操作都是使用回调函数实现。

    实现方式如下(伪代码):

    function One(callback) {	
        if (success) {	
            callback(err, result);	
        } else {	
            callback(err, null);	
        }	
    }	
    	
    One(function (err, result) {	
        //执行完One函数内的内容,成功的结果回调回来向下执行	
    })

    上述代码只是一层级回调,如果代码复杂后,会出现多层级的回调,代码可读性也会很差,那有没有一种方式,不用考虑里面的内容,直接根据结果成功还是失败执行下面的代码呢?有的,Promise(承诺),在ES6中对Promise进行了同意的规范。

    Promise的含义

    Promise原理与讲解

    原理
    1. Promise的三种状态

    注意Promise在某一时刻只能处于一种状态

    1. Promise的状态改变

    Promise的状态改变,状态只能由pending转换为rejected或者rejected,一旦状态改变完成后将无法改变(不可逆性)

    用代码讲原理
    1. 创建一个Promise

    创建Promise需要用到Promise的构造函数来实现,代码如下:

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

    代码分析:

    1. 异步结果传递出去后,then来接 Promise对象将结果传递出来后,使用then方法来获取异步操作的值:代码如下:

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

    代码分析:

    promise.then(function (data){	
        //success	
    })	
    .catch(function(error){	
      //error  	
    })
    1. then的返回值又是怎样呢?先看一段调用两次then的代码:

    //之前创建promise操作后	
    promise.then(function(value){	
        conlose.log(value);  //有值	
    }.then(function(value)	
    {	
       conlose.log(value);   //未定义	
    });

    代码分析:

    几个常用api

    转换的对象是一个常量或者不具备状态的语句,转换后的对象自动处于resolve状态。转换的后的结果和原来一样

    var promise =Promise.resolve("hello world");	
    promise.then(function(result){	
      console.log(result);   //输出结果 hello world	
    })

    转换的对象如果直接是一个异步方法,不可以这么使用。

    代码如下

    promise.all(	
    //一系列promise操作	
    ).then(function(results){	
        	
        	
    }).catch(function(error){	
        	
    });

    代码分析:

    Promise在开发中的应用

    项目开发中promise的应用代码:

    Promise.all([	
                self.count({phoneNumber: mobile, createdOn: {$gt: hour}}),	
                self.count({ip: ip, createdOn: {$gt: hour}})	
            ]).then(function (results) {	
                if (results[0] >= 5) {	
                    return callback({code: -1, message: '短信发送频率过快,每手机号1小时内只能发送5次'});	
                }	
                if (results[1] >= 5) {	
                    return callback({code: -1, message: '短信发送频率过快,每IP1小时内只能发送5次'});	
                }	
                let code = {	
                    phoneNumber: mobile,	
                    code: tool.makeRandomStr(4, 1).toLowerCase(),	
                    createdOn: new Date(),	
                    expiredOn: new Date(new Date().getTime() + (20 * 60 * 1000)),			//20分钟失效	
                    ip: ip,	
                    isUsed: false	
                };	
                self.create(code, function (err, newCode) {	
                    if (newCode) {	
                        sms.sendSMS(mobile, newCode.code, 'ali', function (err, body) {	
                            console.log(body);	
                            if (err)	
                                console.log("短信验证码发送失败:", err);	
                        });	
                        callback({code: 0, message: "验证码已经发送"});	
                    } else {	
                        callback({code: -1, message: "验证码发送失败,请重试"});	
                    }	
                })	
            })

    项目开发过程中使用promise.all的代码,当时是为了实现短信验证码发送前的校验功能。all中的两个promise,第一个是统计时间内该手机号发送验证码数量;第二个是统计时间内该ip发送验证码的数量。

    Promise使用过程中注意事项(坑)

    注意事项在上面原理讲解过程中,基本都提到过,只是重要的事情多说两遍。

    Promise的反思

    Promise的讲解就到这里,但是大家在开发过程中,会发现有些时候多次操作异步会出现很多层级的调用,也就是

    promise.then(...)	
    	
    .then(...)	
    	
    .then(...)

    这种情况,代码虽然看起来会比callback的回调简介和规范了很多,但是还是感觉一些复杂,有没有更好的解决办法呢?请看下一篇博客

    回调的终极使用--async和await的讲解

    ▼原创系列推荐▼1.JavaScript 重温系列(22篇全)
    2.ECMAScript 重温系列(10篇全)
    3.JavaScript设计模式 重温系列(9篇全)
    4.正则 / 框架 / 算法等 重温系列(16篇全)

    640?wx_fmt=png

    640?wx_fmt=png你点的每个赞,我都认真当成了喜欢
    个人博客:http://www.pingan8787.com 微信公众号【前端自习课】和千万网友一起,每日清晨,享受一篇前端优秀文章。 目前已连续推送文章 600+ 天,愿每个人的初心都能一直坚持下去!
  • 相关阅读:
    【转】shell脚本中echo显示内容带颜色的实现方法
    升级到windows10之后的骚操作,安装debian,centos7,支持linux、docker、kubectl命令
    【转】Gradle的使用教程
    【转】.net core开发windows服务
    是时候抛弃Postman了,试试直接在 VS Code上调试并共享你的REST API调用
    Qt-开发环境中的代码中文显示正常,但是运行后是乱码?
    Qt-QMenu的自定义内容-在右击列表中增加一个EDIT框
    2020年十一自驾出行大攻略
    OSG-使用VS2019编译整个源代码方法
    VS2019注册码
  • 原文地址:https://www.cnblogs.com/pingan8787/p/11838146.html
Copyright © 2020-2023  润新知