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 实例方法
then
catch
对于通过
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
在本质上是没有区别的,需要注意分场合使用。