用 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传入要执行的函数,这样,传递。