为什么出现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篇全)

你点的每个赞,我都认真当成了喜欢

【JS】302- 回调地狱解决方案之Promise的更多相关文章

  1. 避免Node.js中回调地狱

    为了解决这个阻塞问题,JavaScript严重依赖于回调,这是在长时间运行的进程(IO,定时器等)完成后运行的函数,因此允许代码执行经过长时间运行的任务. downloadFile('example. ...

  2. js异步回调Async/Await与Promise区别 新学习使用Async/Await

    Promise,我们了解到promise是ES6为解决异步回调而生,避免出现这种回调地狱,那么为何又需要Async/Await呢?你是不是和我一样对Async/Await感兴趣以及想知道如何使用,下面 ...

  3. 回调地狱以及用promise怎么解决回调地狱

    哈哈哈,我又又又回来了,不好意思,最近枸杞喝的比较到位,精力比较旺盛. 现在我们来聊一聊啥是回调地狱,注意是回调地狱啊   不是RB人民最爱拍的那啥地狱啊,来吧,上车吧少年,这是去幼儿园的车 都让开, ...

  4. javascript回调地狱真的只能Promise来解决吗?js回调地狱,Promise。

    javascript的灵活在于函数可以当作函数的参数来传递,以及它的异步回调思想.但是这就带了一个很严重的问题,那就是回调次数过多,会影响代码结构,多层嵌套影响代码的可阅读性,也不便于书写. 举个例子 ...

  5. js中的回调函数 和promise解决异步操作中的回调地狱问题。

    回调函数 : 函数作为参数传递到另外一个函数中.简单数据类型和引入数据类型中的数组和对象作为参数传递大家肯定都不陌生,其实引用数据类型中的函数也是可以的. 事实上大家见到的很多,用到的也很多,比如jQ ...

  6. js动画实现&&回调地狱&&promise

    1. js实现动画 <!DOCTYPE html> <html lang="en"> <head> <meta charset=" ...

  7. js中promise解决callback回调地狱以及使用async+await异步处理的方法

    1.callback回调地狱 function ajax(fn) { setTimeout(()=> { console.log('你好') fn() }, 1000) } ajax(() =& ...

  8. 微信小程序:用 Promise 解决方案代替回调地狱。 修复 this._invokeMethod is not a function 的问题

    /** * 将回调地狱转换为 Promise 形式 * https://blog.csdn.net/SEAYEHIN/article/details/88663740 * raw: wx.downlo ...

  9. Ajax请求回调地狱及解决方案(promise、async和await)

    谈及回调地狱发生得情况和解决办法,就必须追溯到原生ajax请求. 先列出服务器提供的数据接口: // 服务器端接口 app.get('/data1', (req, res) => { res.s ...

随机推荐

  1. linux 内核的RCU本质

    RCU,Read-Copy Update,是一种同步机制,它的本质就是在同步什么?1. 它只有reader-side lock,并且不产生锁竞争.2. 它同步reader-side 临界区和 recl ...

  2. 函数指针和成员函数指针有什么不同,反汇编带看清成员函数指针的本尊(gcc@x64平台)

    函数指针是什么,可能会答指向函数的指针. 成员函数指针是什么,答指向成员函数的指针. 成员函数指针和函数指针有什么不同? 虚函数指针和非虚成员函数指针有什么不同? 你真正了解成员函数指针了吗? 本篇带 ...

  3. 业务领域建模Domain Modeling

    我的工程实践选题为ESP32低功耗的实现,本项目基于ESP32嵌入式开发平台.下文将以需求为基础,对该项目进行领域建模. 一.概念介绍 1.业务建模 1.1 概念介绍 业务建模(Business Mo ...

  4. Java w3c离线手册

    提供给大家使用,懒得找: 前端后端一般都用的到  查看文档 1. JDK_API_1_6_zh_CN.CHM 2.     W3School离线手册(2018.04.01).chm 3.    jqu ...

  5. 学会使用这些,你的Windows可能会焕然一新

    星选哥用Windows也已经好多年了,今天用室友的电脑才发现,桌面真可以影响一个人的心情,从而影响工作,学习,生活. 所以准备推荐一些好用且轻量的小工具,让你时时刻刻有个好心情. 室友的桌面(还有很多 ...

  6. 洛谷P1426-小鱼会有危险吗

    原题链接: https://www.luogu.org/problem/P1426 题面简述: 有一次,小鱼要从A处沿直线往右边游,小鱼第一秒可以游7米,从第二秒开始每秒游的距离只有前一秒的98%98 ...

  7. 网页解析--BeautifulSoup练习

    # coding = utf-8 # BeautifulSoup 主要功能是解析提取HTML数据 # re lxml bs4 # pip install Beautifulsoup4 # from b ...

  8. golang实现rabbitmq消息队列失败尝试

    在工作中发现,有些时候消息因为某些原因在消费一次后,如果消息失败,这时候不ack,消息就回一直重回队列首部,造成消息拥堵. 如是有了如下思路: 消息进入队列前,header默认有参数 retry_nu ...

  9. easywechat微信开发SDK之小微商户进件(二)

    正式开始进件之前需要准备几个东西 1.服务商商户号 2.API密钥 微信服务商后台中设置 3.APIv3密钥 微信服务商后台中设置 4.API证书路径  登录服务商后台下载  生成证书官方又文档的 很 ...

  10. SimpleXML使用详解

    SimpleXML使用详解 介绍 SimpleXML提供了一种简单,直观的方法来处理XML.它只有一个单一类型的类,三个函数和六个方法. 使用SimpleXML SimpleXMLElement 类是 ...