promise的使用
栏目: JavaScript · 发布时间: 8年前
内容简介:promise的使用
本文主要介绍一下 promise 在一些场景下的使用,同时还有对 Promises/A+ 规范的一点个人理解。原本是想总体的讲一下JavaScript异步编程的内容,后由于内容很多,能力有限,目前计划分成几部分。
Promise A+ 规范
为了更好的表述,我把 Promise A+ 规范拆成了两部分介绍:
第一部分规范:
-
一个
Promise的当前状态必须为以下三种状态中的一种:等待态(Pending)、执行态(Fulfilled)和拒绝态(Rejected)。
-
一个
Promise必须提供一个then方法以访问其当前值、终值和据因。promise.then(onFulfilled, onRejected);
第二部分规范:
-
Promise then方法需要return一个新的Promise出来,如下:promise2 = promise1.then(onFulfilled, onRejected);
-
如果
onFulfilled不是函数且promise1成功执行,promise2必须成功执行并返回相同的值;如果onRejected不是函数且promise1拒绝执行,promise2必须拒绝执行并返回相同的据因。 -
如果
promise本身状态变更到Fulfilled之后,返回调用onFulfilled,onRejected的解析值x,与新的promise2进行promise的解析过程[[Resolve]](promise2, x),x的取值不同,有不同的情况: -
若
x为一个promise,则使promise2接受x的状态:var promise2 = new Promise(function(resolve, reject){ resolve(); }).then(function(data){ // 对应于 x 的返回值 return new Promise(function(resolve, reject){ resolve('x = promise'); }); }); promise2.then(function(data){ // 打印 x = promise console.log(data); });为了看的清晰一点,我把链式拆开了,正常是这样子:
new Promise(function(resolve, reject){ resolve(); }).then(function(data){ // 对应于 x 的返回值 return new Promise(function(resolve, reject){ resolve('x = promise'); }); }).then(function(data){ // 打印 x = promise console.log(data); }); -
若
x为一个对象或者函数,如果有then方法,将会执行then方法,then方法this指向x本身,如下:new Promise(function(resolve, reject){ resolve(); }).then(function(data){ // 对应于x的返回值 return { a: 1, then: function(resolve, reject){ // 打印 1 console.log(this.a); resolve({a: 2}); } }; }).then(function(data){ // 打印 2 console.log(data.a); }); -
如果
x没有then方法,那么,x将会做为值来 满足promise2,如下:new Promise(function(resolve, reject){ resolve(); }).then(function(data){ // 对应于x的返回值 return { a: 1 }; }).then(function(data){ // 打印 1 console.log(data.a); });
简单实现的 Promise 对象
这是一个简单实现的 Promise 对象,根据我在上面自己分出来的第一部分规范,实现了『有状态』和 then 方法。
function Promise(fn){
var state = 'pending';
var value;
var deferred;
function resolve(newValue){
value = newValue;
state = 'resolved';
if(deferred) {
handle(deferred);
}
}
function handle(onResolved){
if(state === 'pending') {
deferred = onResolved;
return;
}
onResolved(value);
}
this.then = function(onResolved){
handle(onResolved);
};
fn(resolve);
}
当 new Promise 的时候:
- 执行
fn1并把 resolve 方法交给fn1准备调用 - 同步执行
then方法,将fn2作为参数调用handle方法- 如果
resolve同步执行,那么state变更为resolved,紧接着onResolved也立即执行 - 如果
resolve没有同步执行,那么state依旧是pending,那么将onResolved的引用保存起来,等到resolve异步执行的时候,再调用onResolved方法
- 如果
new Promise(function fn1(resolve){
setTimeout(function(){
resolve('eventual value');
}, 1000);
}).then(function fn2(data){
// 等待 1000ms 后,打印 eventual value
console.log(data);
});
接下来根据我在上面自己分出来的第二部分规范,下面的实现增加了链式和穿透的特性。
function Promise(fn){
var state = 'pending';
var value;
var deferred = null;
function resolve(newValue){
// 这部分是新增的,见注一
if(newValue && typeof newValue.then === 'function') {
newValue.then(resolve);
return;
}
value = newValue;
state = 'resolved';
if(deferred) {
handle(deferred);
}
}
function handle(handler){
if(state === 'pending') {
deferred = handler;
return;
}
// 这部分是新增的,见注二
if(!handler.onResolved) {
handler.resolve(value);
return;
}
var ret = handler.onResolved(value);
handler.resolve(ret);
}
this.then = function(onResolved){
return new Promise(function(resolve){
handle({
onResolved: onResolved,
resolve: resolve
});
});
};
fn(resolve);
}
由于 then() 永远返回一个新的 Promise 对象,导致每次都至少有一个 promise 对象被创建、解决然后被忽略,这就产生了一定程度了内存浪费。
then 方法返回新的 Promise 对象,这个 promise2 要 resolve 的值是 promise1 的返回值。 handle() 函数的最后两行体现了这一点, handler 对象保存了 onResolved() 回调函数和 resolve() 函数的引用。在链式调用中保存了多个 resolve() 函数的拷贝,每一个 promise 对象的内部都拥有一个自己的 resolve() 方法,并在闭包中运行。 这建立起了第一个 promise 与第二个 promise 之间联系的桥梁。
new Promise(function(resolve){
setTimeout(function(){
resolve('promise1 eventual value');
}, 1000);
}).then(function(data){
// 等待 1000ms 后,打印 promise1 eventual value
console.log(data);
return {
then: function(resolve){
setTimeout(function(){
resolve('promise2 eventual value');
}, 1000);
}
}
}).then(function(data){
// 等待 2000ms 后,打印 promise2 eventual value
console.log(data);
});
注一: then 方法内部的返回值可以是 Promise 对象, 如果是要通过 then 方法获取终值,对应第二部分规范第4和5条。
注二: new Promise.then().then(function (data) {}) 里面第一个 then 会被跳过, promise 也会用上一个 promise 返回的终值来传递,对应第二部分规范第2条。
new Promise(function(resolve){
setTimeout(function(){
resolve('promise1 eventual value');
}, 1000);
}).then().then(function(data){
// 等待 1000ms 后,打印 promise1 eventual value
console.log(data);
});
上面的代码一直忽略掉一个问题,错误处理,这里不做引述,原因是我觉得实现方式类似,需要注意的点会在下面讲。
Promise 使用
Promise.all()
当我们想使用 forEach() 的时候,我们可以使用 Promise.all() 。 Promise.all() 以一个 promise 对象组成的数组为输入,返回另一个 promise 对象。这个对象的状态只会在数组中所有的 promise 对象的状态都变为 resolved 的时候才会变成 resolved 。可以将其理解为异步的 for 循环。注意的是,如果输入的一系列 promise 对象中,有一个的状态变为 rejected ,那么 all() 返回的 promise 对象的状态也会变为 rejected 。
var array = [];
for (var i = 0; i < 4; i++) {
(function(){
var a = i;
array.push(new Promise(function(resolve){
setTimeout(function(){
resolve(a);
}, a * 1000);
}));
})(i);
}
new Promise(function(resolve){
resolve();
}).then(function(){
return Promise.all(array);
}).then(function(data){
// 等待 3000ms 后, 打印 [ 0, 1, 2, 3 ]
console.log(data);
});
Promise.resolve()
可以将同步代码包装成 promise 形式,后面可以加 .then() 或者 .catch() ,我觉得在封装接口的时候很适用。
new Promise(function(resolve, reject){
resolve(someSynchronousValue);
}).then(...);
精简为:
Promise.resolve(someSynchronousValue).then(...);
cacth() 和 then(null, …) 并不完全相同
下面两个代码片段是等价的:
somePromise().catch(function(err){
// handle error
});
somePromise().then(null, function(err){
// handle error
});
但是,这并不意味着下面的两个代码片段是等价的
somePromise().then(function(){
return someOtherPromise();
}).catch(function(err){
// handle error
});
somePromise().then(function(){
return someOtherPromise();
}, function(err){
// handle error
});
结论就是,当使用 then(resolveHandler, rejectHandler) , rejectHandler 不会捕获在 resolveHandler 中抛出的错误。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- RecyclerView使用指南(一)—— 基本使用
- 如何使用Meteorjs使用URL参数
- 使用 defer 还是不使用 defer?
- 使用 Typescript 加强 Vuex 使用体验
- [译] 何时使用 Rust?何时使用 Go?
- UDP协议的正确使用场合(谨慎使用)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
互联网+供应链金融创新
宝象金融研究院、零壹研究院 / 电子工业出版社 / 2016-6 / 65.00
供应链金融是一种带有模式创新的金融服务,它真正渗透到了产业运行的全过程。然而,如何探索这种模式的规律?特别是在"互联网+”时代,不同的产业主体如何更好地利用供应链金融促进产业的发展,成为了众多企业关注的话题。零壹财经攥写的《互联网+供应链金融创新》正是立足于这一点,全面总结反映了中国各行各业,以及不同的经营主体如何在立足产业运营的基础上,通过供应链金融来促进产业的发展具有很好的借鉴意义,其丰富的案......一起来看看 《互联网+供应链金融创新》 这本书的介绍吧!