Promise-JavaScript异步编程
Promise是异步编程的一种解决方案。
Why Promise?
Javascript是单线程执行,因而很多的操作都是异步执行的,其中Ajax就是典型的异步操作。对于异步执行传统的解决方案是回调函数,优点是简单、容易理解和使用,缺点是不利于代码的阅读和维护,代码的高度耦合使得程序结构混乱,多层回调嵌套致使流程难以追踪。
ES2015提供了Promise原生对象,能够为异步代码执行结果的成功和失败分别绑定对应的处理方法,可以采用链式的写法串联多个Promise对象,语法上更明晰。
基本用法如下:
|
|
关于链式写法,借用MDN的图参考如下:
Promise有三种状态,分别是pending
表示初始状态;fulfilled
(或resolved
)表示操作成功完成;rejected
表示操作失败。状态的改变只有2种可能,从pending
变成fulfilled
以及从pending
变成rejected
,一旦状态改变,就不会再变。
以Ajax为例:
|
|
目前Chrome、Firefox、Safari的高版本已经支持Promise。
Promise API
.then()
为Promise实例添加状态改变时的回调函数。第一个参数是fulfilled
状态的回调函数,即promise被成功完成执行的回调;第二个参数(可选)是rejected
状态的回调函数,即promise被拒绝或者出现任何错误、异常的过程中被捕捉到时执行的回调,可以不传对抛出的错误不做处理。
继续上面的Ajax的例子,用法如下:
|
|
then
方法返回的是一个新的Promise实例,因此可以使用链式写法。
第一个fulfilled
回调函数的返回有2种情况:第一种是返回某个固定的值,将会作为参数传入第二个then
方法的fulfilled
回调:
|
|
第二种是返回一个Promise对象,则第二个then
将会等待当前状态发生变化之后再按照结果决定调用哪个回调:
|
|
.catch()
catch
方法用于指定发生错误时的回调函数,等同于then(null, rejection)
,如下:
|
|
用catch
能够捕获ajax()抛出的错误和then
方法执行过程中发生的异常或错误,相对then
用catch
处理rejected
状态的写法更佳。
catch
方法返回的还是一个Promise对象,因此接下去还可以继续使用then
方法。
|
|
如果catch
之前没有报错,则直接跳过catch
执行下一个then
方法,这时候这个then
是否报错与前面的catch
就无关了。若当前catch
方法中抛出错误,在当前catch
中是无法捕获的,需要在后面的catch
方法中捕获/处理。
.all() & .race()
all
方法和race
方法同样是将多个Promise实力包装成一个新的Promise实例,如果参数非Promise实例,会先通过Promise.resolve
方法转化,返回的每个成员都是Promise实例。
对于all
方法,只有所有成员都变成fulfilled
,promises
的状态才会变成fulfilled
,这时的返回值组成一个数组传递给promises
的回调函数;只要任何一个成员的状态变为rejected
,promises
的状态就会变成rejected
,第一个被rejected
的实例的返回值传递给promises
的回调函数。
|
|
对于race
方法,只要其中一个成员率先改变状态,就会作为返回值传递给promises
的回调函数。
|
|
.resolve()
resolve
方法用于将传入的参数转化为Promise对象。
|
|
传参可能有四种情况:
- 参数是一个Promise实例:不做任何改变返回。
- 参数是一个thenable对象:指的是具有then方法的对象,转为Promise对象,立即执行该对象的then方法。
- 参数根本不是对象:返回一个状态为Resolved的Promise对象。
- 不带任何参数:直接返回一个Resolved状态的Promise对象。
.reject()
reject
方法会返回一个为rejected
状态的Promise对象。
|
|
reject
方法的参数会原封不动的作为错误的返回值,如:
|
|
即使已经成功获取到posts.json
的内容,控制台仍然会输出Uncaught (in promise) ...
。
总结
对Promise的研究还不是很透彻,从表层看,或许只是对传统回调函数写法的一种封装,提供一种更为简单干净的写法;从某些方面看,除此以外,Promise还具有一些相对严谨的特点,如只有异步操作的结果可以决定当前的状态,且状态一旦确定,即使往下再加其它的逻辑,也不会改变当前的结果。
原文地址:https://www.cnblogs.com/sanxiandoupi/p/11698906.html
- Timber 经典的android Log封装库
- Butter Knife快速开发
- 如何将Markdown文章轻松地搬运到微信公众号并完美地呈现代码内容
- IoC与AOP的那点事儿
- ossec入侵检测日志行为分析
- 从零开始的Spring Session(三)
- 从零开始的Spring Session(一)
- 一个通用的Java正则匹配工具
- 从零开始的Spring Session(二)
- [汇总]2013年度全球重、特大网络安全事件回顾
- android常用接口(一)
- 2014密码时代已死?六种旨在取代传统密码位置的新奇想法
- 程序员你为什么这么累【续】:编码习惯之配置规范
- Spring Security (一) Architecture Overview
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 深入揭秘前端路由本质,手写 mini-router
- 这就是你日日夜夜想要的docker!!!---------Docker四种网络模式解析
- C语言队列的基本操作
- 10款好用到爆的Vim插件,你知道几个?
- 这就是你日日夜夜想要的docker!!!---------Docker Compose容器编排理论+实操
- 模式检验库Meteva笔记:加载本地观测数据
- Go by Example 中文版: SHA1 哈希
- C语言中缀表达式转后缀表达式
- C语言逆波兰表达式计算(后缀表达式计算器)
- SpringBoot+Druid+Mybatis配置多数据源
- C语言共享栈
- C语言二叉树的基本操作
- 《GEO数据挖掘课程》配套练习题
- C语言中缀表达式计算器
- 安装 Rancher2.x 并部署工作负载