【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原理与讲解
原理
Promise的三种状态
注意Promise在某一时刻只能处于一种状态
Promise的状态改变
Promise的状态改变,状态只能由pending转换为rejected或者rejected,一旦状态改变完成后将无法改变(不可逆性)
用代码讲原理
创建一个Promise
创建Promise需要用到Promise的构造函数来实现,代码如下:
var promise=new Promise(function(resolve,reject){
// ...some async code
if(/* 一些异步操作成功*/)
{
resolve(value);
}else
{
reject(error);
}
})
代码分析:
异步结果传递出去后,then来接
Promise对象将结果传递出来后,使用then方法来获取异步操作的值:代码如下:
promise.then(function(value){
//success
},function(error){
});
代码分析:
promise.then(function (data){
//success
})
.catch(function(error){
//error
})
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的更多相关文章
- 避免Node.js中回调地狱
为了解决这个阻塞问题,JavaScript严重依赖于回调,这是在长时间运行的进程(IO,定时器等)完成后运行的函数,因此允许代码执行经过长时间运行的任务. downloadFile('example. ...
- js异步回调Async/Await与Promise区别 新学习使用Async/Await
Promise,我们了解到promise是ES6为解决异步回调而生,避免出现这种回调地狱,那么为何又需要Async/Await呢?你是不是和我一样对Async/Await感兴趣以及想知道如何使用,下面 ...
- 回调地狱以及用promise怎么解决回调地狱
哈哈哈,我又又又回来了,不好意思,最近枸杞喝的比较到位,精力比较旺盛. 现在我们来聊一聊啥是回调地狱,注意是回调地狱啊 不是RB人民最爱拍的那啥地狱啊,来吧,上车吧少年,这是去幼儿园的车 都让开, ...
- javascript回调地狱真的只能Promise来解决吗?js回调地狱,Promise。
javascript的灵活在于函数可以当作函数的参数来传递,以及它的异步回调思想.但是这就带了一个很严重的问题,那就是回调次数过多,会影响代码结构,多层嵌套影响代码的可阅读性,也不便于书写. 举个例子 ...
- js中的回调函数 和promise解决异步操作中的回调地狱问题。
回调函数 : 函数作为参数传递到另外一个函数中.简单数据类型和引入数据类型中的数组和对象作为参数传递大家肯定都不陌生,其实引用数据类型中的函数也是可以的. 事实上大家见到的很多,用到的也很多,比如jQ ...
- js动画实现&&回调地狱&&promise
1. js实现动画 <!DOCTYPE html> <html lang="en"> <head> <meta charset=" ...
- js中promise解决callback回调地狱以及使用async+await异步处理的方法
1.callback回调地狱 function ajax(fn) { setTimeout(()=> { console.log('你好') fn() }, 1000) } ajax(() =& ...
- 微信小程序:用 Promise 解决方案代替回调地狱。 修复 this._invokeMethod is not a function 的问题
/** * 将回调地狱转换为 Promise 形式 * https://blog.csdn.net/SEAYEHIN/article/details/88663740 * raw: wx.downlo ...
- Ajax请求回调地狱及解决方案(promise、async和await)
谈及回调地狱发生得情况和解决办法,就必须追溯到原生ajax请求. 先列出服务器提供的数据接口: // 服务器端接口 app.get('/data1', (req, res) => { res.s ...
随机推荐
- nyoj 242-计算球体积 (pi*r*r*r*4/3)
242-计算球体积 内存限制:64MB 时间限制:3000ms 特判: No 通过数:21 提交数:74 难度:1 题目描述: 根据输入的半径值,计算球的体积. 输入描述: 输入数据有多组,每组占一行 ...
- ACE框架 基于共享内存的分配器 (算法设计)
继承上一篇<ACE框架 基于共享内存的分配器设计>,本篇分析算法部分的设计. ACE_Malloc_T模板定义了这样一个分配器组件 分配器组件聚合了三个功能组件:同步组件ACE_LOCK, ...
- linux hwclock
在Linux中,系统时间(软件时间)和硬件时间,并不会自动同步,系统时间和硬件时间以异步的方式运行,互不干扰.硬件时间的运行,是靠Bios电池来维持,而系统时间,是在系统开机的时候,会自动从Bios中 ...
- win10 下安装zookeeper+Kafka 的详细步骤(2)
Win10 下要使用Kafka需要经过以下三个步骤: 1.安装JDK(需要安装依赖java JDK) 2.安装zookeeper(资源协调,分配管理) 3.使用Kafka开发 ============ ...
- scrapy抓取国家社科基金项目数据库
1.明确任务 目标网站:http://fz.people.com.cn/skygb/sk/index.php/Index/seach 抓取任务:抓取近五年某关键词(例如"能源".” ...
- c#-EntitySet<TEntity>
MSDN 解释: https://msdn.microsoft.com/zh-cn/library/bb341748.aspx 为 LINQ to SQL 应用程序中的一对多关系和一对一关系的集合方提 ...
- LESSON 3- Discrete Memory-less Sources
1. Entropy H[X] - bounds on Lmin 2. Huffman’s algorithm for optimal source code
- 部署高可用 schduler
目录 创建 kube-scheduler 证书和私钥 创建和分发 kubeconfig 文件 创建 kube-scheduler 配置文件 创建kube-scheduler启动文件 启动kube-sc ...
- 【MySQL】数据库课程实验
数据定义 #mysql --version 查版本号 #mysql -uroot -p #登录 show databases; #查询当前服务存在的数据库 #create database test ...
- k 近邻算法解决字体反爬手段|效果非常好
字体反爬,是一种利用 CSS 特性和浏览器渲染规则实现的反爬虫手段.其高明之处在于,就算借助(Selenium 套件.Puppeteer 和 Splash)等渲染工具也无法拿到真实的文字内容. 这种反 ...