Promise是异步编程的一种优雅的解决方案。它相比于回调和事件交互,更加合理和强大。它改善了深度回调的问题。 回调里面还有回调,层级较深的,代码看起来特别凌乱。而通过事件交互会多做一些工作,比如发送事件,监听事件,事件回调等操作。而Promise能够获取异步操作的结果,这样的话,方便进一步处理接下来的逻辑。
Promise,简单来说,他就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。ES6将其写进了语言标准,并原生提供了Promise对象。
Promise的特点
有了Promise对象,就可以将异步操作以同步操作的流程表达出来。避免了层层嵌套的回调。此外Promise对象还对外提供了统一的接口,使控制异步操作更加容易。
Promise也有一些缺点,它一旦开始他就会立即执行,并且无法取消。这个很Promise!
其次,如果不设置回调函数,Promise内部的异常不会反应到外部,也就是说内部出错了也不知道。再者,当处于Pending状态时,无法得知目前进展到哪一步,是刚刚开始,还是即将完成
ES6规定,Promise对象是一个构造函数,用来生成Promise对象。 下面的代码反映了Promise的基本用法。
var promise = new Promise(function(resolve,reject){
//some code
if(操作成功){
resolve(value);
}else{
reject(error);
}
})
Promise的构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject,他们是两个函数,是由JavaScript引擎提供,不用开发者自己部署。
resolve的作用是,将Promise从未完成(Pending)状态变成已成功(Fulfilled)状态,在异步操作成功时调用,并把异步操作的结果作为参数传递出去。 reject的作用是将Promise从未完成(Pending)状态变成已失败(Rejected)状态,在异步操作失败时调用,并把异步操作的错误作为参数传递出去。
Promise实例具有then方法,then方法是定义在Promise.prototype上的,它的作用是为Promise实例添加状态回调改变时的回调函数。then的第一个参数是Resolved状态的回调函数,第二个参数(可选)是Rejected状态下的回调函数。then方法返回的是一个新的Promise对象。注意,不是原来的那个Promise对象,因此可以采用链式写法,即then方法后面还可以再调用then方法。
举个栗子吧
let promise = new Promise((resolve, reject) => {
console.log("Promise!");
resolve();
console.log("Promise Over");
})
setTimeout(() => {
console.log("Hello World!");
}, 0)
console.log("Hi!");
promise.then(() => {
console.log("Resolved!");
})
运行截图如下:
我们来分析下运行结果: promise一旦被创建,就会立即执行,那么代码同步执行,首先就会输出Promise,接下来就会输出Promise Over;因为Promise一系列的操作(then、catch)优先级比setTimeout要高,然后在执行Promise.then,所以接下来是输出Resolved!,最后执行setTimeout,输出Hello World。
Promise.prototype.catch方法是.then(null,reject)的别名,用于指定发生错误的回调。catch可以捕捉到在它之前所有的promise对象内部抛出的异常。
举个栗子:
var doSomething = () => {
return new Promise((resolve, reject) => {
console.log("doSomething");
resolve(1 + x);
console.log("doSomething over");
})
}
doSomething().then((value) => {
console.log(value)
}).catch((err) => {
console.log("hhhhhh");
console.log(err);
})
运行截图如下:
Promise.all方法是将多个Promise实例包装成一个新的Promise实例。
var p = Promise.all([p1,p2,p3])
上面代码中,Promise.all方法接受一个数组作为参数,p1、p2、p3都是Promise对象的实例,如果不是,就会先调用下面讲到的Promise.resolve方法, 将参数转为Promise实例,再进一步处理。(Promise.all方法的参数可以不是数组,但必须具有Iterator接口,且返回的每个成员都是Promise实例。)
p的状态由p1、 p2、 p3决定, 分成两种情况。 (1)只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、 p2、 p3的返回值组成一个数组,传递给p的回调函数。 (2)只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值, 会传递给p的回调函数
举个栗子:
let promise1 = new Promise(resolve => {
console.log("promise1");
resolve(1);
})
let promise2 = new Promise(resolve => {
console.log("promise2");
resolve(2);
})
let promise3 = new Promise(resolve => {
console.log("promise3");
resolve(3);
})
let promises = [promise1, promise2, promise3];
Promise.all(promises).then(value => {
console.log(value);
}).catch(err => {
console.log(err);
})
运行截图:
再看一个栗子:
let promise1 = new Promise(resolve => {
console.log("promise1");
resolve(1);
})
let promise2 = new Promise(resolve => {
console.log("promise2");
resolve(2);
})
let promise3 = new Promise(resolve => {
console.log("promise3");
resolve(x + 3);
}).then((value) => {
console.log(value);
})
let promises = [promise1, promise2, promise3];
Promise.all(promises).then(value => {
console.log(value);
}).catch(err => {
console.log("promise all err:", err);
})
运行截图:
分析: 在上面的代码中,promise1、promise2都正常变为resolved状态,promise3中会发生错误,状态变为Rejected。导致Promise.all这个Promise也会变为Rejected状态。所以会执行Promise.all后面的catch方法,所以在打印promise1,promise2,promise3之后,还会打印promise all err。
再再看一个栗子:
let promise1 = new Promise(resolve => {
console.log("promise1");
resolve(1);
})
let promise2 = new Promise(resolve => {
console.log("promise2");
resolve(2);
})
let promise3 = new Promise(resolve => {
console.log("promise3");
resolve(x + 3);
}).then((value) => {
console.log(value);
}).catch((err) => {
console.log("promise3 err:", err);
})
let promises = [promise1, promise2, promise3];
Promise.all(promises).then(value => {
console.log(value);
}).catch(err => {
console.log("promise all err:", err);
})
运行截图:
分析:promise1,promise2都会进入resolved状态,到了promise3,promise3中有错误,那么会执行promise3后面的catch方法,而catch方法会返回一个新的Promise实例,promise3指向了这个新的promise实例。这个实例在执行完catch之后,也会变成resolved的状态。所以promise1、promise2、promise3都进入了resolved状态,那么Promise.all会执行后面的then方法,但是promise1,promise都有返回值,promise3没有返回值,所以打印出来是[1,2,undefined]。
Promise.race方法也是将多个Promise实例包装成一个新的Promise实例。
var p = Promise.race([p1,p2,p3])
上面代码中, 只要p1、 p2、 p3之中有一个实例率先改变状态, p的状态就跟着改变。 那个率先改变的Promise实例的返回值, 就传递给p的回调函数。 Promise.race方法的参数与Promise.all方法一样, 如果不是Promise实例, 就会先调用下面讲到的Promise.resolve方法, 将参数转为Promise实例, 再进一步处理。
举个栗子:
let promise1 = new Promise(resolve => {
console.log("promise1");
resolve(1);
})
let promise2 = new Promise(resolve => {
console.log("promise2");
resolve(2);
})
let promise3 = new Promise(resolve => {
console.log("promise3");
resolve(3);
})
let promises = [promise1, promise2, promise3];
Promise.race(promises).then(value => {
console.log(value);
}).catch(err => {
console.log(err);
})
运行截图:
Promise.resolve的作用就是将一个对象转换成Promise对象。
Promise.resolve方法的参数分成为以下4种情况。
Promise.reject(reason)方法也会返回一个新的Promise实例,状态为Rejected。
finally方法用于指定不管Promise对象最后状态如何都会执行的操作。
举个栗子:
let p2 = new Promise((resolve, reject) => {
resolve(1);
})
p2.then((value) => {
console.log(value);
}).catch((err) => {
console.log("error:", err);
}).finally(() => {
console.log("finally");
})
输出: 1 finally
那么,Promise,你熟悉它了吗?后面还会有关于Promise的故事,敬请期待~
如有错漏,欢饮大佬们拍砖~
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。