用 new Promise 实例化的Promise对象有三个状态:
“has-resolution” - Fulfilled
onFulfilled “has-rejection” - Rejected
Rejected “unresolve” - Pending
note:
在Chrome中输出 resolve 可以得到 Promise {[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined} ,可以看出 [[PromiseStatus]] 中存储的就是Promise的状态,但是并没有公开访问 [[PromiseStatus]] 的用户API,所以暂时还无法查询其内部状态。
Promise中的 then 的回调只会被调用一次,因为Promise的状态只会从Pending变为Fulfilled或者Rejected,不可逆。
在使用Promise实现有序执行异步的基本格式如下:
//defined Promise async function
functionasyncFun(){
return new Promise((reslove,reject)=>{
if(reslove){
reslove(/*reslove parameter*/);
}else{
reject(new Error(/*Error*/));
}
})
}
//use Promise&then
asyncFun().then(/*function*/).then(/*function*/)...
reslove 方法的参数就是要传给回调函数的参数,即 resolve 将运行得到的结果传出来,而 then 接受该参数给回调继续执行后面的,如果这个 then 的中的函数还会返回Promise,则会重复执行该步骤直到结束。
reject 方法的参数一般是包含了reject原因的Error对象。 reject 和 resolve 一样,也会将自己的参数传出去,接收该参数的是 then 的第二个fun或者是 catch 。其实 .catch 只是 Promise.then(onFulfilled,onRejected) 的别名而已。
一般情况下我们会使用 new Promise 来创建prmise对象,除此之外我们也可以使用 Promise.reslove 和 Promise.reject 来直接创建,例如 Promise.resolve(42) 可以认为是以下代码的语法糖
new Promise((reslove)=>{
reslove(42);
});
这段代码可以让这个Promise对象立即进入resolve状态,并将42传递给后面then里所指定的 onFulfilled 函数。此外 Promise.resolve 还有一个作用,就是将非Promise对象转换为Promise对象。
Promise.reject(value) 与之类似。
var promise = new Promise(function(resolve){
console.log("inner promise"); // 1
resolve(42);
});
promise.then(function(value){
console.log(value); // 3
});
console.log("outer promise"); // 2
/*输出:
"inner promise"
"outer promise"
42
*/
从以上的这段代码我们可以看出 Promise.then() 是异步调用的,这也是Promise设计上规定的,其原因在于 同步调用和异步调用同时存在会导致混乱 。
以上那段代码如果在 调用onReady之前DOM已经载入的话 ,对回调函数进行 同步 调用,如果在 调用onReady之前DOM还没有载入的话 ,通过注册 DOMContentLoader 事件监听器来对回调进行 异步 调用。这会导致该代码在源文件中不同位置输出不同的结果,关于这个现象,有如下几点:
setTimeout 等异步API 所以以上代码应该使用 setTimeout(fn, 0) 进行调用。
functiononReady(fn){
var readyState = document.readyState;
if (readyState === 'interactive' || readyState === 'complete') {
setTimeout(fn, 0);
} else {
window.addEventListener('DOMContentLoaded', fn);
}
}
onReady(function(){
console.log('DOM fully loaded and parsed');
});
console.log('==Starting==');
所以在Promise中 then 是异步的。
如果想实现Promise的链式调用,要求每次链式调用都返回Promise。而then()方法返回就会返回一个Promise,所以只需要给then传入两个回调即可,这两个回调分别在Promise的success和faliure情况下执行。所以现在问题的关键就是如何在第一次调用函数后就返回Promise,方法有两种:
Promise.reslove() 语法糖。 //直接返回Promise
functionpro1(){
return new Promise((reslove,reject)=>{
if(reslove){
reslove(setTimeout(()=>{console.log(1000)},1000));
}
})
}
functionpro2(){
setTimeout(()=>{console.log(2000)},2000);
}
functionpro3(){
setTimeout(()=>{console.log(3000)},3000);
}
pro1().then(pro2()).then(pro3());
//使用Promise.reslove()
functionpro1(){
setTimeout(()=>{console.log(1000)},1000);
}
//这里的pro2,pro3与上面一样
Promise.resolve().then(pro1).then(pro2).then(pro3);
note:
reslove 函数的作用是将Promise对象的状态从“未完成”变为“成功”(即从Pending变为Resolved),在异步操作成功时调用,并将 异步操作的结果作为参数传递出去 ; reject 函数的作用是将Promise对象状态从“未完成”变为“失败”(即从Pending变为Rejected),在异步操作失败时候调用,并将异步操作报出的错误作为参数传递出去; 而想要 then() 里的第一个参数执行,需要Promise是resolve状态,所以需要在启动Promise的时候,如果到达resolve,则给resolve传入要执行的函数,这样,传递。