[js高手之路] es6系列教程 - promise常见用法详解(resolve,reject,catch,then,all,race)

本文主要是介绍[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 等 )

1 setTimeout(function () {
2     console.log(1);
3     setTimeout(function () {
4         console.log(2);
5         setTimeout(function () {
6             console.log(3);
7         }, 1000);
8     }, 1000);
9 }, 1000);

这还是3层,如果4层,5层。。。。,现在代码简单,可能感觉不到,如果console.log换成具体的业务逻辑,那就不得了,假如每个真实的业务逻辑有100行代码,5层嵌套。而业务逻辑中又有很多的嵌套匹配。你能想象吗?如果由于业务需求需要 调换业务的执行顺序?是不是很头疼?不用担心,Promise可以帮你非常灵活的调整:

 1 function next( n ){
 2     return new Promise( function( resolve, reject ){
 3         setTimeout( function(){
 4             resolve( n );
 5         }, 1000 );
 6     } );
 7 }
 8 next( 1 ).then( function( res ){
 9     console.log( res );
10     return next( 2 );
11 } ).then( function( res ){
12     console.log( res );
13     return next( 3 );
14 } ).then( function( res ){
15     console.log( res );
16 } )

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一个值,把一个值往下传递

 1 function next( n ){
 2     return new Promise( function( resolve, reject ){
 3         setTimeout( function(){
 4             resolve( n );
 5         }, 1000 );
 6     } );
 7 }
 8 next( 1 ).then( function( res ){
 9     console.log( res );
10     return 2;
11 } ).then( function( res ){
12     console.log( res );
13     return 3;
14 } ).then( function( res ){
15     console.log( res );
16 } )

reject是把数据传递给then方法的第二个function处理,then方法可以接收2个参数

 1 function next(){
 2     return new Promise( function( resolve, reject ){
 3         var num = Math.floor( Math.random() * 10 );
 4         if ( num <= 5 ) {
 5             resolve( num );
 6         }else {
 7             reject( new Error() );
 8         }
 9     } );
10 }
11 next( 1 ).then( function( res ){
12     console.log( res );
13 }, function( res ){
14     console.log( res );
15 } );
16 console.log( '正常执行' );

当随机数大于等于6的时候,我把一个错误往下抛,然后在then的第二个参数接收到,整个程序还是能够正常运行.

catch也是接收reject传递的数据

 1 function next(){
 2     return new Promise( function( resolve, reject ){
 3         var num = Math.floor( Math.random() * 10 );
 4         if ( num <= 5 ) {
 5             resolve( num );
 6         }else {
 7             reject( new Error() );
 8         }
 9     } );
10 }
11 next( 1 ).then( function( res ){
12     console.log( res );
13 } ).catch( function( res ){
14     console.log( 'reject:'   res );
15 } );
16 console.log( '正常执行' );

Promise.all是等所有的异步资源都加载完毕之后,再执行代码,比如。页面有很多的插件库,一般都是要加载完毕之后,才能有特效效果。Promise.all主要解决的是多个异步模块的依赖问题,必须等大家都加载完毕之后,才执行( 说白了,就是等最慢的那个异步操作执行完了,再打印出结果 )

 1 var count = 0;
 2 function next() {
 3     return new Promise(function (resolve, reject) {
 4         var num = Math.floor(Math.random() * 10);
 5         setTimeout( function(){
 6             console.log( num );
 7             resolve( `第${  count}随机到的值是${num}`);
 8         }, 2000 );
 9     });
10 }
11 Promise.all( [ next(), next(), next() ] ).then( function( res ){
12     console.log( res );
13 } );

三个next()异步操作执行完毕之后,才会一起把他们的resolve结果打印出来

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

 

Promise还有其他的用法,在项目中,这些是比较常用到的

这篇关于[js高手之路] es6系列教程 - promise常见用法详解(resolve,reject,catch,then,all,race)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1076910

相关文章

C++使用栈实现括号匹配的代码详解

《C++使用栈实现括号匹配的代码详解》在编程中,括号匹配是一个常见问题,尤其是在处理数学表达式、编译器解析等任务时,栈是一种非常适合处理此类问题的数据结构,能够精确地管理括号的匹配问题,本文将通过C+... 目录引言问题描述代码讲解代码解析栈的状态表示测试总结引言在编程中,括号匹配是一个常见问题,尤其是在

Debezium 与 Apache Kafka 的集成方式步骤详解

《Debezium与ApacheKafka的集成方式步骤详解》本文详细介绍了如何将Debezium与ApacheKafka集成,包括集成概述、步骤、注意事项等,通过KafkaConnect,D... 目录一、集成概述二、集成步骤1. 准备 Kafka 环境2. 配置 Kafka Connect3. 安装 D

Java中ArrayList和LinkedList有什么区别举例详解

《Java中ArrayList和LinkedList有什么区别举例详解》:本文主要介绍Java中ArrayList和LinkedList区别的相关资料,包括数据结构特性、核心操作性能、内存与GC影... 目录一、底层数据结构二、核心操作性能对比三、内存与 GC 影响四、扩容机制五、线程安全与并发方案六、工程

部署Vue项目到服务器后404错误的原因及解决方案

《部署Vue项目到服务器后404错误的原因及解决方案》文章介绍了Vue项目部署步骤以及404错误的解决方案,部署步骤包括构建项目、上传文件、配置Web服务器、重启Nginx和访问域名,404错误通常是... 目录一、vue项目部署步骤二、404错误原因及解决方案错误场景原因分析解决方案一、Vue项目部署步骤

JavaScript中的reduce方法执行过程、使用场景及进阶用法

《JavaScript中的reduce方法执行过程、使用场景及进阶用法》:本文主要介绍JavaScript中的reduce方法执行过程、使用场景及进阶用法的相关资料,reduce是JavaScri... 目录1. 什么是reduce2. reduce语法2.1 语法2.2 参数说明3. reduce执行过程

C++初始化数组的几种常见方法(简单易懂)

《C++初始化数组的几种常见方法(简单易懂)》本文介绍了C++中数组的初始化方法,包括一维数组和二维数组的初始化,以及用new动态初始化数组,在C++11及以上版本中,还提供了使用std::array... 目录1、初始化一维数组1.1、使用列表初始化(推荐方式)1.2、初始化部分列表1.3、使用std::

Spring Cloud LoadBalancer 负载均衡详解

《SpringCloudLoadBalancer负载均衡详解》本文介绍了如何在SpringCloud中使用SpringCloudLoadBalancer实现客户端负载均衡,并详细讲解了轮询策略和... 目录1. 在 idea 上运行多个服务2. 问题引入3. 负载均衡4. Spring Cloud Load

Springboot中分析SQL性能的两种方式详解

《Springboot中分析SQL性能的两种方式详解》文章介绍了SQL性能分析的两种方式:MyBatis-Plus性能分析插件和p6spy框架,MyBatis-Plus插件配置简单,适用于开发和测试环... 目录SQL性能分析的两种方式:功能介绍实现方式:实现步骤:SQL性能分析的两种方式:功能介绍记录

在 Spring Boot 中使用 @Autowired和 @Bean注解的示例详解

《在SpringBoot中使用@Autowired和@Bean注解的示例详解》本文通过一个示例演示了如何在SpringBoot中使用@Autowired和@Bean注解进行依赖注入和Bean... 目录在 Spring Boot 中使用 @Autowired 和 @Bean 注解示例背景1. 定义 Stud

前端原生js实现拖拽排课效果实例

《前端原生js实现拖拽排课效果实例》:本文主要介绍如何实现一个简单的课程表拖拽功能,通过HTML、CSS和JavaScript的配合,我们实现了课程项的拖拽、放置和显示功能,文中通过实例代码介绍的... 目录1. 效果展示2. 效果分析2.1 关键点2.2 实现方法3. 代码实现3.1 html部分3.2