ES6 - 基础学习(8): Promise 对象
概述
Promise是异步编程的一种解决方案,比传统的解决方案(多层嵌套回调、回调函数和事件)更强大也更合理。从语法上说,Promise是一个对象,从它可以获取异步操作的消息,Promise 还提供了统一的 API,各种异步操作都可以用同样的方法进行处理。
Promise的出现很好的解决了回调地狱这一难题,在之前ES5中多层嵌套回调时,回调代码层次过多,嵌套太深,时间久了既不利于相关代码的理解也不利于代码后期维护以及后续迭代开发,因此Promise才尤为重要。
Promise状态
状态特点:
1、Promise 异步操作有三种状态:pending(进行中)、fulfilled(已成功)、 rejected(已失败)。除了异步操作的结果,任何其他操作都无法改变这个状态。
2、Promise 对象状态只有两种变化形式:从 pending 变为 fulfilled 或从 pending 变为 rejected。只要Promise 对象处于 fulfilled 或 rejected 状态,Promise 对象状态就不会再改变(即 resolved(已定型))。
状态缺点:
1、无法取消Promise ,Promise一旦建立就会立即执行,且中途无法取消。
2、如果不设置回调函数,Promise内部抛出的错误,不会反应到外部,Promise会吃掉自己的错误。
3、当处于 pending(进行中) 状态时,无法得知 Promise目前进展到哪一个阶段(是刚刚开始还是即将完成)。
Promise用法
ES6中,Promise对象是一个构造函数,用来生成Promise实例。Promise构造函数接受一个函数(既流程中第一步要执行的函数)作为参数,该函数的两个参数分别是resolve和reject,它们是两个函数,由 JavaScript 引擎提供,不用自己部署。
let state = true;
let promise = new Promise(function (resolve, reject) {
// ... do something
if (state) { // 异步操作成功
resolve(value); // resolve函数:将 Promise 对象状态从"进行中"变为"已成功"(即从 pending 变为 fulfilled),在异步操作成功后调用,并将异步操作返回的结果,作为参数传递出去;
} else { // 异步操作失败
reject(error); // reject函数:将 Promise 对象状态从"进行中"变为"已失败"(即从 pending 变为 rejected),在异步操作失败后调用,并将异步操作产生的错误,作为参数传递出去。
}
});
/* 或者分开写 */
// 流程中第一步要执行的函数,即 Promise 构造函数接受的参数函数
let step1 = function (resolve, reject) {
// ... do something
if (state) { // 异步操作成功
resolve(value); // resolve函数:将 Promise 对象状态从"进行中"变为"已成功"(即从 pending 变为 fulfilled),在异步操作成功后调用,并将异步操作返回的结果,作为参数传递出去;
} else { // 异步操作失败
reject(error); // reject函数:将 Promise 对象状态从"进行中"变为"已失败"(即从 pending 变为 rejected),在异步操作失败后调用,并将异步操作产生的错误,作为参数传递出去。
}
};
let promise = new Promise(step1);
Promise 实例方法
Promise 实例提供了很多其他方法, 这些方法基本都定义在原型对象 Promise.prototype 上。
then 方法:then方法返回的是一个新的Promise实例(从参数就可看出,第二个Promise实例执行的是第二步了),因此then方法可以采用链式写法,即then方法后再调用另一个then方法。
/* then方法 */
let state = true;
function step1(resolve, reject) {
console.log('第一步开始');
if (state) {
resolve('第一步执行成功!');
} else {
reject('第一步执行失败!');
}
}
function step2(resolve, reject) {
console.log('第二步开始');
if (state) {
resolve('第二步操作成功!');
} else {
reject('第二步操作失败!');
}
} // Promise实例生成后,在实例 then方法内分别指定 resolved状态 和 rejected状态的回调函数。
// then方法接受两个回调函数作为参数,第一个回调函数是Promise对象状态变为resolved时调用,第二个回调函数是Promise对象状态变为rejected时调用。其中,第二个函数是可选参数,非必须提供,这两个函数都接受Promise对象传出的值作为参数。
new Promise(step1).then(function (value) {
console.log(value); // 第一步执行成功!
state = false;
return new Promise(step2); // 返回的是一个新的Promise实例(从参数就可看出,第二个Promise实例执行的是第二步了),因此then方法可以采用链式写法,即then方法后再调用另一个then方法。
}).then(function (value) { // 新Promise实例的then方法(链式写法)
console.log(value); // 第二步操作成功!
}, function (value) {
console.log(value); // 第二步操作失败!
});

catch 方法:catch方法是 .then(null, rejection) 或 .then(undefined, rejection) 的别名,用于指定异步操作发生错误时的回调函数。
/* catch方法 */
let state = false;
function step1(resolve, reject) {
console.log('第一步开始');
if (state) {
resolve('第一步执行成功!');
} else {
reject('第一步执行失败!');
}
} new Promise(step1).then(function (value) {
console.log(value);
}).catch(function (error) {
console.log('Promise发生错误:', error);
});
// new Promise(step1)返回一个Promise对象,如果该对象状态变为resolved,则调用then方法指定的回调函数;
// 如果异步操作抛出错误,状态就会变为rejected,则调用catch方法指定的回调函数,处理这个错误。同时 then方法指定的回调函数,如果运行中抛出错误,也会被catch方法捕获。
let promiseError = new Promise(function (resolve, reject) {
// throw new Error('Promise抛出的错误!');
reject(new Error('test')); // reject方法的作用,在这等同于throw,都是抛出错误
});
promiseError.catch(function(error) {
console.log(error);
}); // Promise对象产生的错误如果不处理(即没有catch方法回调函数处理),Promise对象抛出的错误也不会传递到外层代码,并不会影响外层代码的执行(即系统不会有任何反应,原进程照常执行,不会中断和退出)。
// 这与传统的try/catch代码块不同,会一直向后(冒泡)传递,直到被catch捕获为止。
let promiseCatch = new Promise(function (resolve, reject) {
reject(xx) // Promise对象异步操作失败,传出未声明参数
});
promiseCatch.catch(function(error) {
console.log(error);
console.log(xxxx); // catch中未声明参数
});
setTimeout(function () {
console.log('系统照常执行,并未受到影响!');
},2000);

// 如果 Promise对象状态已经变成resolved,则无论是抛出错误还是reject传出错误,都是无效的。操作不会执行,参数传递不出去。
let promiseError = new Promise(function (resolve, reject) {
resolve("It's resolved!"); // Promise对象状态已经变成resolved。
throw new Error("It's rejected!");
reject(new Error("It's rejected!"));
});
promiseError.then(function (value) {
console.log(value); // It's resolved!
}).catch(function (error) {
console.log(error);
});

// 不管 Promise对象后面跟了多少个 then方法,建议最后用catch方法结尾,这样不但可以处理 Promise对象内部发生的错误,还可以处理流程过程中 then方法报出的错误。
// 1、最后一步不跟catch方法
function step1(resolve, reject) {
resolve(xx); // xx变量 未声明
}
function step2(resolve, reject) {
reject(yyyy); // yyyy变量 未声明
} new Promise(step1).then(function(value) { // 由于xx变量未声明,此处then方法不执行,Promise对象异步执行报出的错误被下面catch方法捕获
console.log(value);
}).catch(function(error) {
console.log('catch捕获到错误:', error); // catch捕获到错误: ReferenceError: xx is not defined
}).then(function() {
return new Promise(step2)
}).then(function(value) { // 同样yyyy变量也未声明,此处then方法不执行,但后面没有其他catch方法,所以 step2报出的错误将不会被捕获,也不会得到处理
console.log(value);
}); // 2、最后一步跟catch方法
function step1(resolve, reject) {
resolve(xx);
}
function step2(resolve, reject) {
reject(yyyy);
} new Promise(step1).then(function(value) {
console.log(value);
}).then(function() {
console.log('貌似你没被执行!');
return new Promise(step2)
}).then(function(value) {
console.log(value);
}).catch(function(error) {
console.log('catch捕获到错误:', error); // catch捕获到错误: ReferenceError: xx is not defined
});
// 从打印可以看出,catch方法捕获到了错误(系统执行报出的第一个错误),同时中断后续代码(后续流程)执行。

图1:最后一步不跟catch方法 图2:最后一步跟catch方法
ES6 - 基础学习(8): Promise 对象的更多相关文章
- ES6基础知识(Promise 对象)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- es6学习笔记--promise对象
Promise对象是为了简化异步编程.解决回调地狱情况 Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果.从语法上说,Promise 是一个对象,从它可 ...
- ES6系列_14之promise对象的简单使用
1.产生原因 在前端开发中,最常见的的就是"回调",我相信很多人对于这个"回调"可谓是印象深刻呢.究其原因是因为层层回调会造成所谓的“回调地狱 (callbac ...
- js-ES6学习笔记-Promise对象(2)
1.Promise实例具有then方法,也就是说,then方法是定义在原型对象Promise.prototype上的.它的作用是为Promise实例添加状态改变时的回调函数. 2.Promise.pr ...
- js-ES6学习笔记-Promise对象
1.Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大. 2.所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作) ...
- ES6 - 基础学习(6): 对象扩展
对象对于JavaScript至关重要,在ES6中对象又加了很多新特性. 对象字面量:属性的简洁表示法 ES6允许对象的属性直接写变量,这时候属性名是变量名,属性值是变量值. let attr1 = & ...
- ES6 基础学习
ECMAScript 6 标准入门 一.let和const let命令 let命令,用来声明变量.它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效:是块级作用域,且let不允许 ...
- ES6 - 基础学习(1): 开发环境搭建
现在Chrome浏览器已经很好的支持ES6了,但有些低版本的浏览器或其他浏览器还是不支持ES6的语法,因此实际项目开发或上线过程中就需要把ES6的语法转变成ES5的语法.项目开发过程中 Webpack ...
- python基础学习18----面向对象简述
这里就不再讲面向对象的相关概念知识或者与面向过程的比较了,直接进入类的学习 1.类的创建 class people: def __init__(self):#构造函数 pass sfencs=peop ...
随机推荐
- python self用法
在定义类的过程中,无论是显式的创建类的构造方法,还是向类中添加实例方法,都要将self参数作为方法的第一个参数. class Person: def __init__(self): print(&qu ...
- python面向对象(一切皆对象)
使用面向对象的思想设计一个乌龟的角色: 表面特征:绿色.有4条腿.重10kg.有外壳等等 行为特征:爬.吃.睡觉.将头和四肢缩到壳里等等 class tortoise: bodycolor = &qu ...
- 「 从0到1学习微服务SpringCloud 」11 补充篇 RabbitMq实现延迟消费和延迟重试
Mq的使用中,延迟队列是很多业务都需要用到的,最近我也是刚在项目中用到,就在跟大家讲讲吧. 何为延迟队列? 延迟队列就是进入该队列的消息会被延迟消费的队列.而一般的队列,消息一旦入队了之后就会被消费者 ...
- scikit-learn基础
一.scikit-learn基础 sklearn.ensemble模块有两种基于决策树的算法----随机森林和极端随机树
- mongo 查询 距离 某个点 多少 米距离 感谢 提供的数据。 感谢 mvc的 demo 。反正 就是各种感谢 文档之类的。
昨天 去面试来着, 问了一下mong . 我记得mong支持 地理位置索引的,说了一下. 然后 面试官说 查询某个点 的 多少米范围, 这个该怎么实现? 我懵逼了.... 回去 查询了一下. 发现有 ...
- 「雅礼集训 2017 Day2」棋盘游戏
祝各位圣诞后快乐(逃) 题目传送门 分析: 首先棋盘上的路径构成的图是一张二分图 那么对于一个二分图,先求出最大匹配,先手如果走到关键匹配点,只要后手顺着匹配边走,由于不再会出现增广路径,所以走到最后 ...
- POJ Expanding Rods
点击打开题目 题目大意 给定L,n,C,L为红色线段,L(1+n*C)为绿色弧,求两者中点的距离 二分圆心角度数,接下来就是几何的能力了 根据正弦定理,可得: Lsinθ=rsin(90°−θ) 则弧 ...
- 基于Flask框架搭建视频网站的学习日志(一)
------------恢复内容开始------------ 基于Flask框架搭建视频网站的学习日志(一)2020/02/01 一.Flask环境搭建 创建虚拟环境 初次搭建虚拟环境 搭建完虚拟环境 ...
- linux--->linux 各个文件夹及含义
1./bin 是binary的缩写 存放linux常用命令 2./lib 该目录用来存放系统动态链接共享库,几乎所有的应用程序都会用到该目录下的共享库. 3./dev 该目录包含了Linux系统中使用 ...
- day03_流程控制语句
day03_流程控制语句 建议: 凡是次数确定的场景多用for循环,否则用while循环. 三元运算符 由?:符号表示的,具体的含义其实就和if-else结构的含义差不多,这种运算符会将某个条 ...