
即 setTimeout 自身就会先消耗一定的时间。
ok,那么说了半天Promise到底怎么和他们比较呢? 他的价值在哪里呢?
价值都在这里了!看下面的这个例子:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>testsettimeout</title>
</head>
<body>
<div class="wrap">
</div>
<script>
let promise = new Promise(function(resolve, reject) {
console.log('Promise! 我是Promise对象里的函数,我最早出现是因为我要给后面一个耗时的家伙提供数据a');
var a = 20;
resolve(a);
});
promise.then(function(value) {
console.log('哈哈哈,我得到数据a了,要开始执行喽。我是一个非常耗时的操作,依赖前面的数据,但是我想快一点执行,这有利于用户体验,所以别把我放在后头啊;我被放在了一个新的线程上,不会阻塞别人的');
for (var i = 0; i < 1000000; i++) {
var li = document.createElement("li");
document.querySelector(".wrap").appendChild(li);
}
console.log("执行完毕");
});
console.log('Hi! 我是什么都不依赖的程序,但我也想快一点执行,不能委屈我啊');
</script>
</body>
</html>
说明: 在已经执行过的情况下,录制屏幕,然后按下刷新键,可以发现,在new Promise里的函数是立即执行的,紧接着是promise.then()之后的函数立即执行,而没有等待then()函数,最后进入then()函数,说了一堆废话,最后大约2 ~ 3s之后执行结束。故promise.then()函数才是真正的异步执行。
promise实现:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>promise</title>
</head>
<body>
<script>
function Mypromise(fn) {
this.state = 'pending';
this.value = void 0;
this.doneList = [];
this.failList = [];
// 在创建一个promise的时候,需要传递一个fn函数,接受参数resolve和reject。
// resolve和reject目前还没有定义,因为用户是直接调用的,如resolve('success'),所以这个resolve方法是需要我们自己来定义的。
var self = this;
function resolve(value) {
// 一旦resolve,状态机的状态由pending -> resolved
// 并且在resolve的时候状态必须是pending,才能转换状态。
// 异步执行所有回调函数
setTimeout(function () {
if (self.state == 'pending') {
self.state = 'resolved'
self.value = value;
// 一旦成功,我们就可以执行所有promise上挂载的 doneList 中所有的回调函数了,并将value值传递过去
for (var i = 0; i < self.doneList.length; i++) {
self.doneList[i](value);
}
}
}, 0);
}
function reject(reason) {
// 一旦reject,状态机的状态由pending -> rejected
// 在reject的时候状态必须是pending,才能转化状态。
// 异步执行所有回调函数
setTimeout(function () {
if (self.state == 'pending') {
self.state = 'rejected'
self.value = reason;
// 一旦失败,我么就可以把所有的 failList 调用了,并且传递 reason
for (var i = 0; i < self.failList.length; i++) {
self.failList[i](reason);
}
}
}, 0);
}
fn(resolve, reject);
}
Mypromise.prototype = {
constructor: Mypromise,
// then方法接受成功时的回调和失败时的回调
// 实际上,这里的then方法就像路由中的注册路由一样,是一个注册的过程,而没有真正的调用。
// 并且then是支持链式调用的,所以then应该返回一个promise。 如果返回旧的,那么因为状态不能改变,所以没有意义,所以我么一定要返回一个新的promise,这样这个状态机才可以再次正常的工作。
then: function (onResolved, onRejected) {
var self = this;
// 对于then而言,最终要返回一个新的promise,这样才支持链式调用。
var promise2;
// 这里要做一个判断,看传递进来的是否是一个函数,如果是,则不变,如果不是,就拒绝。
// 如果是promise.then().then().then(function (value) {}); 我们还希望拿到value,那么就要把value在即使没有用到onResolved的时候也传递下去。对于reason也是如此。
onResolved = typeof onResolved == 'function' ? onResolved : function (value) {return value;}
onRejected = typeof onRejected == 'function' ? onRejected : function (reason) { return reason;}
// 下面这一部分是比较核心的内容,因为then最终要返回一个promise,但是,这个promise究竟应该怎么返回呢? 如果在then中,用户就返回了promise,那么我们就用户的,如果用户用的不是promise,那么我么就要自己封装好这个promise了。
// 注意: promise也是需要异步调用的,所以可以使用promise进行封装。
switch(this.state) {
case 'resolved':
// 如果resolved,则返回一个新的promise
return promise2 = new Mypromise(function (resolve, reject) {
setTimeout(function () {
try {
// 这里相当于直接就给执行了,看看返回的是什么值,如果是promise,那么直接就使用这个promise了。
var x = onResolved(self.value);
if (x instanceof Mypromise) {
x.then(resolve, reject);
}
} catch (e) {
reject(e);
}
}, 0)
})
case 'rejected':
// 如果rejected,同样也需要返回一个新的promise
return promise2 = new Mypromise( function (resolve, reject) {
setTimeout(function () {
try {
var x = onRejected(self.value);
if (x instanceof Mypromise) {
x.then(resolve, reject);
}
} catch (e) {
reject(e);
}
}, 0);
})
// 如果是pending状态,我们就不能确定使用什么,等到状态确定之后才能决定。
case 'pending':
return promise2 = new Mypromise(function () {
// 注意:一般then都是执行的这里, 即在then的时候进行注册,把相应的成功的和失败的都会初测在这里,push的是一个函数,所以这里的onResolved还是没有执行的。
setTimeout(function () {
self.doneList.push(function (value) {
try {
var x = onResolved(self.value)
if (x instanceof Mypromise) {
x.then(resolve, reject)
} else {
onResolved(value);
}
} catch (e) {
reject(e)
}
});
console.log(self.doneList)
self.failList.push(function (value) {
try {
var x = onRejected(self.data);
if (x instanceof Mypromise) {
x.then(resolve, reject);
}
} catch (e) {
}
});
}, 0);
})
default:
console.log(this.state);
return;
}
},
catch: function (onRejected) {
return this.then(null, onRejected);
}
}
var promise = new Mypromise(function (resolve, reject) {
if (5 > 3) {
resolve('success');
}
});
promise.then(function (value) {
console.log('哈哈哈哈或');
});
</script>
</body>
</html>总结
以上所述是小编给大家介绍的ES6中的promise,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!
