[js高手之路] es6系列教程 - promise常见用法详解(resolve,reject,catch,then,all,race)
关于promise我在之前的文章已经应用过好几次,如[js高手之路]Node.js+jade+express+mongodb+mongoose+promise实现todolist,本文就来讲解下promise的常见用法.
为什么会有promise,他的作用是什么?
promise主要是为了解决js中多个异步回调难以维护和控制的问题.
什么是promise?

从图中,我们可以看出,Promise是一个函数,这个函数上有在项目中常用的静态方法:all, race, reject,resolve等,原型对象上有有catch, then等方法.也就是说,如果要调用catch和then方法,需要一个Promise的实例( new Promise ), 而静态方法可以用函数本身调用,如:Promise.all, Promise.race等,好了,至此,至少知道Promise是什么,但是还是不知道怎么用他提供的方法,接下来我们从一个需求开始,在javascript中,经常有这样的需求:
1,页面上有一个按钮,一个ul,点击按钮的时候,每隔1秒钟向ul的后面追加一个li, 一共追加10个,li的内容从0开始技术( 0, 1, 2, ....9 ),这个在我的博客文章中,出现好几次
2,每隔1秒钟输出递增的数字,如( 1, 2, 3, 4, 5 等 )
3,红绿灯( 红->(等2秒)->绿( 等2秒 )->黄( 等2秒 ) -> 红等,如此循环下去
4,node.js中的爬虫,爬文章url->爬文章内容->爬文章url->爬文章内容
好了,太多这类应用了,这类应用叫做异步回调( 执行完一件事,才能接着往下执行),如果出现多次,就会产生多层嵌套( 回调地狱 ),维护和控制异步过程非常的麻烦和困难,如:
每隔1秒钟输出递增的数字,如( 1, 2, 3 等 )
setTimeout(function () {
console.log(1);
setTimeout(function () {
console.log(2);
setTimeout(function () {
console.log(3);
}, 1000);
}, 1000);
}, 1000);
这还是3层,如果4层,5层。。。。,现在代码简单,可能感觉不到,如果console.log换成具体的业务逻辑,那就不得了,假如每个真实的业务逻辑有100行代码,5层嵌套。而业务逻辑中又有很多的嵌套匹配。你能想象吗?如果由于业务需求需要 调换业务的执行顺序?是不是很头疼?不用担心,Promise可以帮你非常灵活的调整:
function next( n ){
return new Promise( function( resolve, reject ){
setTimeout( function(){
resolve( n );
}, 1000 );
} );
}
next( 1 ).then( function( res ){
console.log( res );
return next( 2 );
} ).then( function( res ){
console.log( res );
return next( 3 );
} ).then( function( res ){
console.log( res );
} )
Promise的构造函数接收一个参数,是函数,并且传入两个参数:resolve,reject,分别表示异步操作执行成功后的回调函数和异步操作执行失败后的回调函数。按照标准来讲,其实resolve是将Promise的状态置为fullfiled,reject是将Promise的状态置为rejected,promise的常用用法.
一般是用一个函数嵌套,返回一个promise对象,为什么这么用?
因为then,catch方法需要一个Promise实例,才能把多个异步执行的操作,根据resolve和reject的执行状态一层层往下执行.
当我们执行next( 1 )的时候,在next函数中返回一个promise对象,一秒钟之后,通过resolve把n( 就是 1 )传递给then方法的第一个function,参数res就是resolve传递过来的数据,所以1秒钟后输出1,紧接着我在return next( 2 ),这个时候又调用了一次Promise对象,一秒钟后,通过resolve把n ( 就是 2 )传递给下一个then方法的第一个function, 参数res就收到n( 2 )的值,所以1秒钟后输出2。。。下面输出3的过程跟刚才分析的一样,有一点一定要注意,在then方法中的function 调用的next方法,一定要用return ,否则不会通过resolve把数据往下传递( 通俗点讲就是下一个异步操作,接收不到上一步的结果 ).
then中的function也可以return一个值,把一个值往下传递
function next( n ){
return new Promise( function( resolve, reject ){
setTimeout( function(){
resolve( n );
}, 1000 );
} );
}
next( 1 ).then( function( res ){
console.log( res );
return 2;
} ).then( function( res ){
console.log( res );
return 3;
} ).then( function( res ){
console.log( res );
} )
reject是把数据传递给then方法的第二个function处理,then方法可以接收2个参数
function next(){
return new Promise( function( resolve, reject ){
var num = Math.floor( Math.random() * 10 );
if ( num <= 5 ) {
resolve( num );
}else {
reject( new Error() );
}
} );
}
next( 1 ).then( function( res ){
console.log( res );
}, function( res ){
console.log( res );
} );
console.log( '正常执行' );
当随机数大于等于6的时候,我把一个错误往下抛,然后在then的第二个参数接收到,整个程序还是能够正常运行.
catch也是接收reject传递的数据
function next(){
return new Promise( function( resolve, reject ){
var num = Math.floor( Math.random() * 10 );
if ( num <= 5 ) {
resolve( num );
}else {
reject( new Error() );
}
} );
}
next( 1 ).then( function( res ){
console.log( res );
} ).catch( function( res ){
console.log( 'reject:' + res );
} );
console.log( '正常执行' );
Promise.all是等所有的异步资源都加载完毕之后,再执行代码,比如。页面有很多的插件库,一般都是要加载完毕之后,才能有特效效果。Promise.all主要解决的是多个异步模块的依赖问题,必须等大家都加载完毕之后,才执行( 说白了,就是等最慢的那个异步操作执行完了,再打印出结果 )
var count = 0;
function next() {
return new Promise(function (resolve, reject) {
var num = Math.floor(Math.random() * 10);
setTimeout( function(){
console.log( num );
resolve( `第${++count}随机到的值是${num}`);
}, 2000 );
});
}
Promise.all( [ next(), next(), next() ] ).then( function( res ){
console.log( res );
} );
三个next()异步操作执行完毕之后,才会一起把他们的resolve结果打印出来

Promise.race,只要最快的异步执行完毕之后,就执行then,不会等待其他的异步操作

Promise还有其他的用法,在项目中,这些是比较常用到的
[js高手之路] es6系列教程 - promise常见用法详解(resolve,reject,catch,then,all,race)的更多相关文章
- [js高手之路] es6系列教程 - 对象功能扩展详解
第一:字面量对象的方法,支持缩写形式 //es6之前,这么写 var User = { name : 'ghostwu', showName : function(){ return this.nam ...
- [js高手之路] es6系列教程 - 迭代器与生成器详解
什么是迭代器? 迭代器是一种特殊对象,这种对象具有以下特点: 1,所有对象都有一个next方法 2,每次调用next方法,都会返回一个对象,该对象包含两个属性,一个是value, 表示下一个将要返回的 ...
- [js高手之路] es6系列教程 - var, let, const详解
function show( flag ){ console.log( a ); if( flag ){ var a = 'ghostwu'; return a; } else { console.l ...
- [js高手之路] es6系列教程 - 迭代器,生成器,for...of,entries,values,keys等详解
接着上文[js高手之路] es6系列教程 - 迭代器与生成器详解继续. 在es6中引入了一个新的循环结构for ....of, 主要是用来循环可迭代的对象,那么什么是可迭代的对象呢? 可迭代的对象一般 ...
- [js高手之路] es6系列教程 - 函数的默认参数详解
在ES6之前,我们一般用短路表达式处理默认参数 function show( a, b ){ var a = a || 10; var b = b || 20; console.log( a, b ) ...
- [js高手之路] es6系列教程 - 箭头函数详解
箭头函数是es6新增的非常有意思的特性,初次写起来,可能会觉得别扭,习惯之后,会发现很精简. 什么是箭头函数? 箭头函数是一种使用箭头( => )定义函数的新语法, 主要有以下特性: 不能通过n ...
- [js高手之路] es6系列教程 - 不定参数与展开运算符(...)
三个点(...)在es6中,有两个含义: 用在形参中, 表示传递给他的参数集合, 类似于arguments, 叫不定参数. 语法格式: 在形参面前加三个点( ... ) 用在数组前面,可以把数组的值 ...
- [js高手之路]es6系列教程 - 解构详解
解构通俗点说,就是通过一种特定格式,快捷的读取对象/数组中的数据的方法, es6之前,我们通过对象名称[键] 读取数据 var User = { 'name' : 'ghostwu', 'age' : ...
- [js高手之路] es6系列教程 - Set详解与抽奖程序应用实战
我们还是从一些现有的需求和问题出发,为什么会有set,他的存在是为了解决什么问题? 我们看一个这样的例子,为一个对象添加键值对 var obj = Object.create( null ); obj ...
随机推荐
- 【HotSpot】jps命令行详解
jps (JVM Process Status) jdk提供的一个查看当前Java进程的小工具. 命令输入格式:jps [选项 ] [ 主机号 ] [options]选项 : -q:仅输出VM标识符, ...
- Google reCAPTCHA 人机身份验证
1. 适合范围 注册及登录某些使用Google验证码的网站,如https://zaif.jp/,会要求进行人机身份验证 2. 方法介绍 下载老D的Google hosts以及一键更新批处理程序 老D博 ...
- 浅谈CSS模块化
为什么要CSS模块化? 你是否为class命名而感到苦恼? 你是否有怕跟别人使用同样class名而感到担忧? 你是否因层级结构不清晰而感到烦躁? 你是否因代码难以复用而感到不爽? 你是否因为commo ...
- 记录-新建一个web应用的过程与曲折
第一步/ 打开eclipse,菜单栏下,File–New–Other-,打开后找到web–Dynamic Web Project,然后单击Next. 解释一下,Dynamic ,动态的,变化的,Dyn ...
- Jmeter常用功能详解
嘻嘻,忙碌的一周,马上就到周四了~明天就是周五了,可以去嗨了! 这几天正式成立了一个微信订阅号,旨在免费帮助需要入门软件测试的小白! 各位走过路过的亲,欢迎订阅哦:扫描二维码即可订阅
- 最大流dinic模板
循环版,点的编号从0开始: ; ; const int INF = 0x3f3f3f3f; struct Edge { int to, next, cap, flow; }edge[MAXM]; in ...
- Volatile和Synchronized对可见性和原子性的支持
在学习并发编程的时候,遇见了volatile和synchronized关键字问题,volatile是可以保证可见性,但无法保证原子性,synchronized关键字由于其是加锁机制,肯定是可以保证原子 ...
- Ext.grid.EditorGridPanel保存
用get方法传递编辑的数据会出现乱码,解决get乱码的方法就是encodeURI(param),然后在后台转码: String strJson = new String(request.getPar ...
- Jmeter遇到的坑
一.分布式获取不到结果需要改配置文件 在jmeter.properties文件找到mode=Standard去掉# 二.有一个请求要循环查询进度,当进度为100为,跳出循环.这个要怎么操作? ${ ...
- HandlerThread实现数字时钟
1.描述 刚看完Android多线程编程,对HandlerThread比较感兴趣,趁热巩固练习,实现一个了数字时钟,希望对学习HandlerThread有所帮助.如下: 启动一个HandlerThre ...