这里不说Promise是什么,网上有各种各样的版本,所以在这里,我只想记录一下 Promise 的执行过程和记录下来使用注意事项的东西,再添加了点个人理解而已
对了,我还写了一篇《理解ES6中的Generator》
工作流
先上代码
function asyncFunction(){
return new Promise(function(resolve,reject){
setTimeout(function(){
resolve('Async Hello World');
},16);
});
}
asyncFunction().then(function(value){
console.log(value);
}).catch(function(error){
console.log(error);
});
在代码中,我们用到了构造函数 Promise
来创建一个新建新promise对象;然后,执行promise对象时,执行用.then
调用返回值时的回调函数
asyncFunction
这个函数会返回promise对象, 对于这个promise对象,我们调用它的then
方法来设置resolve后的回调函数, catch
方法来设置发生错误时的回调函数
该promise对象会在setTimeout
之后的16ms时被resolve
, 这时 then 的回调函数会被调用,并输出Async Hello world
状态
用new Promise
实例化的promise对象有以下三个状态。左侧为在 ES6 Promises 规范中定义的术语, 而右侧则是在 Promises/A+ 中描述状态的术语
1、 "has-resolution" - Fulfilled
resolve(成功)时。此时会调用 onFulfilled
2、 "has-rejection" - Rejected
reject(失败)时。此时会调用 onRejected
3.、"unresolved" - Pending
既不是resolve也不是reject的状态。也就是promise对象刚被创建后的初始化状态等
另外,Fulfilled和Rejected这两个中的任一状态都可以表示为Settled(不变的)
4、Settled
resolve(成功) 或 reject(失败)。
实战
语法糖
Promise.resolve
Promise.resolve(42);
可以认为是以下代码的语法糖
new Promise(function(resolve){
resolve(42);
});
在这段代码中的 resolve(42);
会让这个promise对象立即进入确定(即resolved)状态,并将 42
传递给后面then里所指定的 onFulfilled
函数
方法 Promise.resolve(value);
的返回值也是一个promise对象
Promise.reject
Promise.reject(new Error("出错了"))
就是下面代码的语法糖
new Promise(function(resolve,reject){
reject(new Error("出错了"));
});
Thenable
ES6 Promises里提到了Thenable这个概念,简单来说它就是一个非常类似promise的东西
就像我们有时称具有 .length
方法的非数组对象为Array like一样,thenable指的是一个具有 .then
方法的对象
这种将thenable对象转换为promise对象的机制要求thenable对象所拥有的 then
方法应该和Promise所拥有的 then
方法具有同样的功能和处理过程,在将thenable对象转换为promise对象的时候,还会巧妙的利用thenable对象原来具有的 then
方法
then是异步的
.then 中指定的方法调用是异步进行的,如下
var promise = new Promise(function (resolve){
console.log("inner promise");
resolve(42);
});
promise.then(function(value){
console.log(value);
});
console.log("outer promise");
执行后是
inner promise
outer promise
42
为了避免同时使用同步、异步调用可能引起的混乱问题,Promise在规范上规定Promise只能使用异步调用方式,所以Promise保证了每次调用都是以异步方式进行的
链式写法
promise可以写成方法链的形式,如下
aPromise.then(function taskA(value){
// task A
}).then(function taskB(vaue){
// task B
}).catch(function onRejected(error){
console.log(error);
});
从代码上乍一看, aPromise.then(...).catch(...)
像是针对最初的 aPromise
对象进行了一连串的方法链调用
然而实际上不管是 then
还是 catch
方法调用,都返回了一个新的promise对象
我们判断一下两个方法返回的到底是不是新的promise对象,如下
var aPromise = new Promise(function (resolve) {
resolve(100);
});
var thenPromise = aPromise.then(function (value) {
console.log(value);
});
var catchPromise = thenPromise.catch(function (error) {
console.error(error);
});
console.log(aPromise === thenPromise);
console.log(thenPromise === catchPromise);
执行返回
false
false
100
===
是严格相等比较运算符,我们可以看出这三个对象都是互不相同的,这也就证明了 then
和 catch
都返回了和调用者不同的promise对象
Promise.all
Promise.all
接收一个 promise对象的数组作为参数,当这个数组里的所有promise对象全部变为resolve或reject状态的时候,它才会去调用 .then
方法
function timerPromisefy(delay) {
return new Promise(function(resolve) {
setTimeout(function() {
resolve(delay);
}, delay);
});
}
var startDate = Date.now();
Promise.all([
timerPromisefy(1),
timerPromisefy(32),
timerPromisefy(64),
timerPromisefy(128)
]).then(function(values) {
console.log(Date.now() - startDate + 'ms');
console.log(values);
});
执行返回
129ms
[ 1, 32, 64, 128 ]
这个promise对象数组中所有promise都变为resolve状态的话,至少需要128ms
从上述结果可以看出,传递给 Promise.all 的promise并不是一个个的顺序执行的,而是同时开始、并行执行的
Promise.race
Promise.race
的使用方法和Promise.all
一样,接收一个promise对象数组为参数,当其中一个promise对象进入 FulFilled 或者 Rejected 状态的话,就会去调用 .then
方法
function timerPromisefy(delay) {
return new Promise(function(resolve) {
setTimeout(function() {
resolve(delay);
}, delay);
});
}
Promise.race([
timerPromisefy(1),
timerPromisefy(32),
timerPromisefy(64),
timerPromisefy(128)
]).then(function(value) {
console.log(value);
});
执行返回
1
上面的代码创建了4个promise对象,这些promise对象会分别在1ms,32ms,64ms和128ms后变为确定状态,即FulFilled,并且在第一个变为确定状态的1ms后, .then
注册的回调函数就会被调用,这时候确定状态的promise对象会调用 resolve(1)
因此传递给 value 的值也是1,控制台上会打印出1
来
需要注意的是
Promise.race
在第一个promise对象变为Fulfilled之后,并不会取消其他promise对象的执行
补充
- 使用promise.then(onFulfilled, onRejected) 的话
在 onFulfilled 中发生异常的话,在 onRejected 中是捕获不到这个异常的
- 在 promise.then(onFulfilled).catch(onRejected) 的情况下
then 中产生的异常能在 .catch 中捕获
- .then 和 .catch 在本质上是没有区别的
需要分场合使用
总结
之前看《你不知道的JavaScript(中卷)》的时候已经涉及到,看得不太懂,所以这次再看一次迷你书,然后又翻了一下中卷,全懂了,大概就这样,感觉没啥好总结的,写个demo或许会更好
内容比较多,至此~
参考
- liubin.org/promises-book/
基本上全书已看,也把书中的一些参考也看了点
本文由 Chakhsu Lau 创作,采用 知识共享署名4.0 国际许可协议进行许可。
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名。
COOL! 谢谢分享,学到了 then 和 catch 会返回一个新的 Promise 对象。
另外 Promise.all 虽然是同时开始并发执行,但是返回的数组顺序跟输入保持一致,在需要保证返回顺序的情况下很好用。
Promise 配合 async await 更好用
一个是链式写法,一个是同步写法,没有什么配合什么好的~
并不是 async await 才是异步最好的方式 你的promise 无非返回的是一个异步函数,在真正的产出环境(其前后端分离)中,promise就会出现回调的厄运,所以建议还是全面的使用es7的提案
大佬~你说得对!
咦,这个主题真心感觉也很不错呀!
谢谢支持~😁
怎么把html页面单独拿出来哦 不会php