es6 -- 透彻掌握Promise的使用,读这篇就够了
Promise的重要性我认为我没有必要多讲,概括起来说就是必须得掌握,而且还要掌握透彻。这篇文章的开头,主要跟大家分析一下,为什么会有Promise出现。
在实际的使用当中,有非常多的应用场景我们不能立即知道应该如何继续往下执行。最重要也是最主要的一个场景就是ajax请求。通俗来说,由于网速的不同,可能你得到返回值的时间也是不同的,这个时候我们就需要等待,结果出来了之后才知道怎么样继续下去。
// 简单的ajax原生实现
var url = 'https://hq.tigerbrokers.com/fundamental/finance_calendar/getType/2017-02-26/2017-06-10';
var result; var XHR = new XMLHttpRequest();
XHR.open('GET', url, true);
XHR.send(); XHR.onreadystatechange = function() {
if (XHR.readyState == 4 && XHR.status == 200) {
result = XHR.response;
console.log(result);
}
}
在ajax的原生实现中,利用了onreadystatechange事件,当该事件触发并且符合一定条件时,才能拿到我们想要的数据,之后我们才能开始处理数据。
这样做看上去并没有什么麻烦,但是如果这个时候,我们还需要做另外一个ajax请求,这个新的ajax请求的其中一个参数,得从上一个ajax请求中获取,这个时候我们就不得不如下这样做:
var url = 'https://hq.tigerbrokers.com/fundamental/finance_calendar/getType/2017-02-26/2017-06-10';
var result; var XHR = new XMLHttpRequest();
XHR.open('GET', url, true);
XHR.send(); XHR.onreadystatechange = function() {
if (XHR.readyState == 4 && XHR.status == 200) {
result = XHR.response;
console.log(result); // 伪代码
var url2 = 'http:xxx.yyy.com/zzz?ddd=' + result.someParams;
var XHR2 = new XMLHttpRequest();
XHR2.open('GET', url, true);
XHR2.send();
XHR2.onreadystatechange = function() {
...
}
}
}
当出现第三个ajax(甚至更多)仍然依赖上一个请求的时候,我们的代码就变成了一场灾难。这场灾难,往往也被称为回调地狱。
因此我们需要一个叫做Promise的东西,来解决这个问题。
// 一个简单的封装
function want() {
console.log('这是你想要执行的代码');
} function fn(want) {
console.log('这里表示执行了一大堆各种代码'); // 其他代码执行完毕,最后执行回调函数
want && want();
} fn(want);
利用回调函数封装,是我们在初学JavaScript时常常会使用的技能。
确保我们想要的代码压后执行,除了利用函数调用栈的执行顺序之外,我们还可以利用上一篇文章所述的队列机制。
function want() {
console.log('这是你想要执行的代码');
}
function fn(want) {
// 将想要执行的代码放入队列中,根据事件循环的机制,我们就不用非得将它放到最后面了,由你自由选择
want && setTimeout(want, 0);
console.log('这里表示执行了一大堆各种代码');
}
fn(want);
如果浏览器已经支持了原生的Promise对象,那么我们就知道,浏览器的js引擎里已经有了Promise队列,这样就可以利用Promise将任务放在它的队列中去。
function want() {
console.log('这是你想要执行的代码');
}
function fn(want) {
console.log('这里表示执行了一大堆各种代码');
// 返回Promise对象
return new Promise(function(resolve, reject) {
if (typeof want == 'function') {
resolve(want);
} else {
reject('TypeError: '+ want +'不是一个函数')
}
})
}
fn(want).then(function(want) {
want();
})
fn('1234').catch(function(err) {
console.log(err);
})
看上去变得更加复杂了。可是代码变得更加健壮,处理了错误输入的情况。
为了更好的往下扩展Promise的应用,这里需要先跟大家介绍一下Promsie的基础知识。
一、 Promise对象有三种状态,他们分别是:
- pending: 等待中,或者进行中,表示还没有得到结果
- resolved(Fulfilled): 已经完成,表示得到了我们想要的结果,可以继续往下执行
- rejected: 也表示得到结果,但是由于结果并非我们所愿,因此拒绝执行
这三种状态不受外界影响,而且状态只能从pending改变为resolved或者rejected,并且不可逆。在Promise对象的构造函数中,将一个函数作为第一个参数。而这个函数,就是用来处理Promise的状态变化。
new Promise(function(resolve, reject) {
if(true) { resolve() };
if(false) { reject() };
})
上面的resolve和reject都为一个函数,他们的作用分别是将状态修改为resolved和rejected
二、 Promise对象中的then方法,可以接收构造函数中处理的状态变化,并分别对应执行。then方法有2个参数,第一个函数接收resolved状态的执行,第二个参数接收reject状态的执行。
function fn(num) {
return new Promise(function(resolve, reject) {
if (typeof num == 'number') {
resolve();
} else {
reject();
}
}).then(function() {
console.log('参数是一个number值');
}, function() {
console.log('参数不是一个number值');
})
}
fn('hahha');
fn(1234);
then方法的执行结果也会返回一个Promise对象。因此我们可以进行then的链式执行,这也是解决回调地狱的主要方式。
function fn(num) {
return new Promise(function(resolve, reject) {
if (typeof num == 'number') {
resolve();
} else {
reject();
}
})
.then(function() {
console.log('参数是一个number值');
})
.then(null, function() {
console.log('参数不是一个number值');
})
}
fn('hahha');
fn(1234);
then(null, function() {}) 就等同于catch(function() {})
三、Promise中的数据传递
大家自行从下面的例子中领悟吧。
var fn = function(num) {
return new Promise(function(resolve, reject) {
if (typeof num == 'number') {
resolve(num);
} else {
reject('TypeError');
}
})
}
fn(2).then(function(num) {
console.log('first: ' + num);
return num + 1;
})
.then(function(num) {
console.log('second: ' + num);
return num + 1;
})
.then(function(num) {
console.log('third: ' + num);
return num + 1;
});
// 输出结果
first: 2
second: 3
third: 4
OK,了解了这些基础知识之后,我们再回过头,利用Promise的知识,对最开始的ajax的例子进行一个简单的封装。看看会是什么样子。
var url = 'https://hq.tigerbrokers.com/fundamental/finance_calendar/getType/2017-02-26/2017-06-10'; // 封装一个get请求的方法
function getJSON(url) {
return new Promise(function(resolve, reject) {
var XHR = new XMLHttpRequest();
XHR.open('GET', url, true);
XHR.send(); XHR.onreadystatechange = function() {
if (XHR.readyState == 4) {
if (XHR.status == 200) {
try {
var response = JSON.parse(XHR.responseText);
resolve(response);
} catch (e) {
reject(e);
}
} else {
reject(new Error(XHR.statusText));
}
}
}
})
} getJSON(url).then(resp => console.log(resp));
为了健壮性,处理了很多可能出现的异常,总之,就是正确的返回结果,就resolve一下,错误的返回结果,就reject一下。并且利用上面的参数传递的方式,将正确结果或者错误信息通过他们的参数传递出来。
现在所有的库几乎都将ajax请求利用Promise进行了封装,因此我们在使用jQuery等库中的ajax请求时,都可以利用Promise来让我们的代码更加优雅和简单。这也是Promise最常用的一个场景,因此我们一定要非常非常熟悉它,这样才能在应用的时候更加灵活。
四、Promise.all
当有一个ajax请求,它的参数需要另外2个甚至更多请求都有返回结果之后才能确定,那么这个时候,就需要用到Promise.all来帮助我们应对这个场景。
Promise.all接收一个Promise对象组成的数组作为参数,当这个数组所有的Promise对象状态都变成resolved或者rejected的时候,它才会去调用then方法。
var url = 'https://hq.tigerbrokers.com/fundamental/finance_calendar/getType/2017-02-26/2017-06-10';
var url1 = 'https://hq.tigerbrokers.com/fundamental/finance_calendar/getType/2017-03-26/2017-06-10'; function renderAll() {
return Promise.all([getJSON(url), getJSON(url1)]);
} renderAll().then(function(value) {
// 建议大家在浏览器中看看这里的value值
console.log(value);
})
五、 Promise.race
function renderRace() {
return Promise.race([getJSON(url), getJSON(url1)]);
}
renderRace().then(function(value) {
console.log(value);
})
嗯,我所知道的,关于Promise的基础知识就这些了,如果还有别的,欢迎大家补充。
es6 -- 透彻掌握Promise的使用,读这篇就够了的更多相关文章
- 透彻掌握Promise的使用,读这篇就够了
透彻掌握Promise的使用,读这篇就够了 Promise的重要性我认为我没有必要多讲,概括起来说就是必须得掌握,而且还要掌握透彻.这篇文章的开头,主要跟大家分析一下,为什么会有Promise出现. ...
- 前端基础进阶(十三):透彻掌握Promise的使用,读这篇就够了
Promise的重要性我认为我没有必要多讲,概括起来说就是必须得掌握,而且还要掌握透彻.这篇文章的开头,主要跟大家分析一下,为什么会有Promise出现. 在实际的使用当中,有非常多的应用场景我们不能 ...
- 想了解MQ,读这篇就够了
一.简介 MQ全称为Message Queue-消息队列,是一种应用程序对应用程序的消息通信,一端只管往队列不断发布信息,另一端只管往队列中读取消息,发布者不需要关心读取消息的谁,读取消息者不需要关心 ...
- 了解 HTTPS,读这篇文章就够了
今天接到个活儿,让我科普 HTTPS .讲 HTTP 我都“方”,想要通俗易懂的说完 HTTPS, 我有点“圆”.在讲什么是 HTTPS 之前,我们先来看个漫画. △ 图片来源于阮一峰的网络日志 ...
- es6中的promise对象
Promise是异步里面的一种解决方案,解决了回调嵌套的问题,es6将其进行了语言标准,同意了用法,提供了`promise`对象, promise对象有三种状态:pending(进行中) .Resol ...
- ES6中的Promise用法
Node的产生,大大推动了Javascript这门语言在服务端的发展,使得前端人员可以以很低的门槛转向后端开发. 当然,这并不代表迸发成了全栈.全栈的技能很集中,绝不仅仅是前端会写一些HTML和一些交 ...
- vuex+Es6语法补充-Promise
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式,采用 集中式存储管理 单页面的状态管理/多页面状态管理 使用步骤: // 1.导入 import Vuex from 'vuex' // ...
- js promise看这篇就够了
一.背景 大家都知道nodejs很快,为什么会这么快呢,原因就是node采用异步回调的方式来处理需要等待的事件,使得代码会继续往下执行不用在某个地方等待着.但是也有一个不好的地方,当我们有很多回调的时 ...
- 史上最强Java NIO入门:担心从入门到放弃的,请读这篇!
本文原题“<NIO 入门>,作者为“Gregory M. Travis”,他是<JDK 1.4 Tutorial>等书籍的作者. 1.引言 Java NIO是Java 1.4版 ...
随机推荐
- PostgreSQL Replication之第四章 设置异步复制(5)
4.5 使流复制更健壮 当连接到master时,slave要做的第一件事情是赶上master.但是,这会一直工作吗?我们已经看到,我们可以使用由基于流和基于文件组成的混合设置.这给了我们一些额外的安全 ...
- Win 7系统倒计时!
3月25日消息,近日微软已经开始通知当前正在使用Windows 7的用户,该操作系统“接近尾声”.微软表示计划在2020年1月14日终止对Windows 7的所有支持.但结束Windows 7似乎并不 ...
- updatedb---创建或更新slocate命令所必需的数据库文件
updatedb命令用来创建或更新slocate命令所必需的数据库文件.updatedb命令的执行过程较长,因为在执行时它会遍历整个系统的目录树,并将所有的文件信息写入slocate数据库文件中. 补 ...
- uname---用于打印当前系统相关信息
uname命令用于打印当前系统相关信息(内核版本号.硬件架构.主机名称和操作系统类型等). 语法 uname(选项) 选项 -a或--all:显示全部的信息: -m或--machine:显示电脑类型: ...
- python Web抓取(二)selenium模块的使用、对浏览器的按键操作及错误处理
建议以下帖子: 教你在Windows上搭建Python+Selenium环境:https://blog.csdn.net/huilan_same/article/details/52888262 py ...
- Unity 编辑器学习(四)之 静态游戏物体
一.Static GameObjects 关于静态对象的信息往往可以预先在编辑器里计算,不需要实时计算,进而优化性能,明显降低DrawCall. 各种Static说明: Lightmapping: 用 ...
- HDU 3277 Marriage Match III
Marriage Match III Time Limit: 4000ms Memory Limit: 32768KB This problem will be judged on HDU. Orig ...
- 一 Balancer regionCountCost 权重。
原文如下地址 : http://www.cnblogs.com/cenyuhai/p/3650943.html 看源码很久了,终于开始动手写博客了,为什么是先写负载均衡呢,因为一个室友入职新公司了,然 ...
- Testin实验室:陌陌APP通过率为94.92% 基本满足移动社交需求
Testin实验室:陌陌APP通过率为94.92% 基本满足移动社交需求 2014/11/10 · Testin · 独家评測 11月8日,国内移动社交应用陌陌公开向美国证券交易委员会提交了IPO申请 ...
- Android——bootchart
bootchart:android原生自带的开机性能查看机制.通过收集android开机过程中的各种log数据,终于能够图表的形式展现各个进程在开机过程中的性能.(博客不能断-) 撰写不易,转载需注明 ...