我们在写代码的时候肯定写过回调函数 (如下所示), 但是我们写的毁掉一般都是一二级, 当我们遇到毁掉层级比较多的时候怎么解决? 一直写回调代码会比较繁琐, 维护也比较困难, 这个时候我们会选择使用 Promise 对象来解决.
- function funA(a, funB) {
- if (a<10) {
- funB()
- }
- }
- funA(11, function() {
- // 回调
- })
什么是 Promise
Promise 是异步编程的一种解决方案, 它有三种状态, 分别是 pending - 进行中, resolved - 已完成, rejected - 已失败
当 Promise 的状态从 pending 转变为 resolved 或 rejected 时, 会执行相应的方法, 并且状态一旦改变, 就无法再次改变状态, 这也是它名字 promise - 承诺的由来
Promise 的基本用法
Promise 对象是一个构造函数, 用来生成 Promise 实例. 实例化的 Promise 对象会立即执行.
声明一个 promise 对象
- let promise = new Promise ( (resolve, reject) => {
- if ( success ) {
- resolve(val) // pending --> resolved 参数将传递给对应的回调方法
- } else {
- reject(error) // pending --> rejectd
- }
- } )
- function promise () {
- return new Promise ( function (resolve, reject) {
- if ( success ) {
- resolve(val) // pending --> resolved 参数将传递给对应的回调方法
- } else {
- reject(error) // pending --> rejectd
- }
- } )
- }
- // 实例化的 Promise 对象会立即执行.
- let promise = new Promise(function(resolve, reject) {
- console.log('Promise'); //1
- resolve(val);
- });
- promise.then(function(val) {
- console.log('resolved.'); //3
- });
- console.log('Hi!'); //2
- // Promise
- // Hi!
- // resolved
- new Promise((resolve, reject) => {
- return resolve(1);
- // 后面的语句不会执行
- console.log(2);
- }).then(r => {
- console.log(r);
- })
- Promise.prototype.then()
.then() 方法使 Promise 原型链上的方法, 它包含两个参数方法, 分别是已成功 resolved 的回调和已失败 rejected(可选) 的回调
- promise.then(
- val => { console.log('resolved') },
- error => { console.log('rejected') }
- )
- Promise.prototype.catch()
.catch() 的作用是捕获 Promise 的错误, 与 then() 的 rejected 回调作用几乎一致. 但是由于 Promise 的抛错具有冒泡性质, 能够不断传递, 这样就能够在下一个 catch() 中统一处理这些错误. 同时 catch() 也能够捕获 then() 中抛出的错误, 所以建议不要使用 then() 的 rejected 回调, 而是统一使用 catch() 来处理错误. 同样, catch() 中也可以抛出错误, 由于抛出的错误会在下一个 catch 中被捕获处理, 因此可以再添加 catch().
- promise.then(
- (val) => { console.log(val) }
- ).catch(
- (error) => { console.log(error) }
- )
- Promise.prototype.finally()
finally 方法用于指定不管 Promise 对象最后状态如何, 都会执行的操作. 该方法是 ES2018 引入标准的.
- promise
- .then(result => {...})
- .catch(error => {...})
- .finally(() => {console.log("一定执行")});
- Promise.all()
Promise.all 方法用于将多个 Promise 实例, 包装成一个新的 Promise 实例. 参数为 Promise 对象数组. 如果有不是 Promise 的对象, 将会先通过下面的 Promise.resolve() 方法转换
const p = Promise.all([p1, p2, p3]);
p 的状态由 p1,p2,p3 决定, 分成两种情况.
(1) 只有 p1,p2,p3 的状态都变成 fulfilled,p 的状态才会变成 fulfilled, 此时 p1,p2,p3 的返回值组成一个数组, 传递给 p 的回调函数.
(2) 只要 p1,p2,p3 之中有一个被 rejected,p 的状态就变成 rejected, 此时第一个被 reject 的实例的返回值, 会传递给 p 的回调函数.
Promise.race()
参数与 Promise.all() 相同, 不同的是, 参数中的 p1,p2,p3 只要有一个改变状态, promise 就会立刻变成相同的状态并执行对于的回调.
- const p = Promise.race([p1, p2, p3]);
- Promise.resolve()
有时需要将现有对象转为 Promise 对象, Promise.resolve 方法就起到这个作用.
const jsPromise = Promise.resolve($.ajax('/whatever.json'));
但 Promise.resolve() 会根据参数情况返回不同的 Promise:
参数是 Promise: 原样返回
参数带有 then 方法: 转换为 Promise 后立即执行 then 方法
参数不带 then 方法, 不是对象或没有参数: 返回 resolved 状态的 Promise
Promise.reject()
Promise.reject(reason) 方法也会返回一个新的 Promise 实例, 该实例的状态为 rejected.Promise.reject() 会直接返回 rejected 状态的 Promise
应用
图片加载
- const preloadImage = function (path) {
- return new Promise(function (resolve, reject) {
- const image = new Image();
- image.onload = resolve;
- image.onerror = reject;
- image.src = path;
- });
- };
学习阮一峰大神的 es6
来源: http://www.qdfuns.com/article/18271/3a1fda3cf27340ebdee420d997147ca0.html