ES6学习-Promise
近期学习的ES6,关于Promise的部分。
Promise 的基本格式
var promise = getAsyncPromise('fileA.txt');
promise.then(function(result) {
// 获取文件内容成功时的处理
}).catch(function(error) {
// 获取文件内容失败时的处理
})API
三种类型的API
Constructor 构造函数
Promise
var promise = new Promise(function(resolve, reject) {
// 异步处理
// 处理结束后,调用resolve或 reject
})Instance Method 实例方法
thencatch对于通过
new生成的promise对象为了设置其值resolve/reject时调用的回调函数,可以使用promise.then()实例方法。promise.then(onFulfilled, onRejected),成功时onFulfilled会被调用,失败时onRejected会被调用onFulfilled和onRejected都是可选参数
Static Method 静态方法
Promise.all()
Promise.race()
Promise.resovle()
Promise.reject()Promise的状态
有三种状态
has-resolution = Fulfilled
has-rejection = Rejected
unresolved = Pending
没有公开访问状态的api方法
从Pending转换为
Fulfilled或Rejected之后,promise的状态不会再改变Fulfilled和Rejected这两种状态是不可变的当promise的对象状态发生变化时,用
.then来定义只会被调用一次的函数
编写promise对象的处理方法
被resolve后的处理,可以在
.then方法中传入想要调用的函数被reject后的处理,可以在
.then的第二个参数或者是在.catch方法中设置想要调用的函数一般说来,使用
.catch来将resolve和reject处理分开来写是比较推荐的做法
Promise.resolve
静态方法
Promise.resolve(value)可以认为是new Promise()方法的快捷方式比如
Promise.resolve(42);可以认为是以下代码的语法糖
new Promise(function(resolve){
resolve(42);
});方法
Promise.resolve(value);的返回值也是一个promise对象Promise.resolve方法另一个作用就是将 thenable 对象转换为promise对象。thenable指的是一个具有.then方法的对象。除了在编写使用Promise的类库等软件时需要对Thenable有所了解之外,通常作为end-user使用的时候,我们可能不会用到此功能。
Promise.reject
Promise.reject(error)是和Promise.resolve(value)类似的静态方法比如
Promise.reject(new Error("出错了"))就是下面代码的语法糖形式
new Promise(function(resolve,reject){
reject(new Error("出错了"));
});Promise只能进行异步操作?
Promise在规范上规定 Promise 只能使用异步调用方式。
即使在调用
promise.then注册回调函数的时候promise对象已经是确定的状态,Promise也会以异步的方式调用该回调函数关于这个问题,在 Effective JavaScript 的 第67项 不要对异步回调函数进行同步调用 中也有详细介绍。
绝对不能对异步回调函数(即使在数据已经就绪)进行同步调用。
如果对异步回调函数进行同步调用的话,处理顺序可能会与预期不符,可能带来意料之外的后果。
对异步回调函数进行同步调用,还可能导致栈溢出或异常处理错乱等问题。
如果想在将来某时刻调用异步回调函数的话,可以使用
setTimeout等异步API。
由于Promise保证了每次调用都是以异步方式进行的,所以我们在实际编码中不需要调用
setTimeout来自己实现异步调用
Promise#then
- promise可以写成方法链的形式
aPromise.then(function taskA(value){
// task A
}).then(function taskB(vaue){
// task B
}).catch(function onRejected(error){
console.log(error);
});promise chain 中如何传递参数
- Task A 中 return 的返回值,会在 Task B 执行时传给它
function doubleUp(value) {
return value * 2;
}
function increment(value) {
return value + 1;
}
function output(value) {
console.log(value);// => (1 + 1) * 2
}
var promise = Promise.resolve(1);
promise
.then(increment)
.then(doubleUp)
.then(output)
.catch(function(error){
// promise chain中出现异常的时候会被调用
console.error(error);
});Promise#then不仅仅是注册一个回调函数那么简单,它还会将回调函数的返回值进行变换,创建并返回一个promise对象。
每次调用then都会返回一个新创建的promise对象
- then 的错误使用方法
function badAsyncCall() {
var promise = Promise.resolve();
promise.then(function() {
// 任意处理
return newVar;
});
return promise;
}- 这种写法有很多问题,首先在
promise.then中产生的异常不会被外部捕获,此外,也不能得到 then 的返回值,即使其有返回值。- 正确的写法
function anAsyncCall() {
var promise = Promise.resolve();
return promise.then(function() {
// 任意处理
return newVar;
});
}promise.all
promise.all接收一个promise对象的数组作为参数,当这个数组里的所有promise对象全部变为resolve或reject状态的时候,它才会调用.then方法。传递给
Promise.all的promise并不是一个个的顺序执行,而是同时开始、并行执行的。每个promise的结果(resolve或reject时传递的参数值),和传递给
Promise.all的promise数组的顺序是一致的。
promise.race
promise.race使用方法和Promise.all一样,接收一个promise对象数组为参数。当数组里只要有一个promise对象进入FulFilled或者Rejected状态,就会继续进行后面的处理。
-当一个promise变为确定(FulFilled)状态后,并不会取消其他promise对象的执行。
then or catch
使用
promise.then(onFulfilled, onRejacted)的话,在onFulfilled中发生异常的话,在onRejected中是捕获不到这个异常的。在
promise.then(onFulfilled).catch(onRejected)的情况下,then中产生的异常能在.catch中捕获.then和.catch在本质上是没有区别的,需要注意分场合使用。