|
导读网页的本质就是超级文本标记语言,通过结合使用其他的Web技术(如:脚本语言、公共网关接口、组件等),可以创造出功能强大的网页。因而,超级文本标记语言是万维网(Web)编程的基础,也就是说万维网是建立... 网页的本质就是超级文本标记语言,通过结合使用其他的Web技术(如:脚本语言、公共网关接口、组件等),可以创造出功能强大的网页。因而,超级文本标记语言是万维网(Web)编程的基础,也就是说万维网是建立在超文本基础之上的。超级文本标记语言之所以称为超文本标记语言,是因为文本中包含了所谓“超级链接”点。 本篇文章给大家带来的内容是关于promise对象的深入解析(附示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。js中的异步,刚开始的时候都是用回调函数实现的,所以如果异步嵌套的话,就有出现回调地狱,使得代码难以阅读和难以维护,后来es6出现了promise,解决了回调地狱的问题。现在我们就自己写代码实现一下promise,这样才能深入理解promise的运行机制,对以后使用promise也能够更加得心应手。开始之前可以先看下promise的官网promise/A+ 先来看下promise的用法 new Promise((resolve,reject)=>{
resolve(1);
reject(11);
}).then(res=>{
console.log(res);
setTimeout(()=>{
return new Promise((resolve,reject)=>{
resolve(2)
})
},1000)
}).then(res2=>{
console.log(res2);
});控制台打印 先分析下上面这段代码,先提出几个问题 状态机promise中有个状态机的概念,先说下为什么要有状态机的概念呢,因为promise的状态是单向变化的,有三种状态,pending,fullfilled,rejected,而这三种状态只能从pending->fullfilled或者pending->rejected这两种形式,也就是说执行了fullfilled之后,就不会执行rejected。这就解释了上面的第一个问题。 下面我们来看下具体实现的完整代码 const PENDING = 'PENDING';
const FULLFILLED = 'FULLFILLED';
const REJECTED = 'REJECTED';
class Promise{
constructor(fn){
this.status = PENDING;//状态
this.data = undefined;//返回值
this.defercb = [];//回调函数数组
//执行promise的参数函数,并把resolve和reject的this绑定到promise的this
fn(this.resolve.bind(this),this.reject.bind(this));
}
resolve(value){
if(this.status === PENDING){
//只能pending=>fullfied
this.status = FULLFILLED;
this.data = value;
this.defercb.map(item=>item.onFullFilled());
}
}
reject(value){
if(this.status === PENDING){
//只能pending=>rejected
this.status = REJECTED;
this.data = value;
this.defercb.map(item=>item.onRejected());
}
}
then(resolveThen,rejectThen){
//如果没有resolveThen方法,保证值可以穿透到下一个then里有resolveThen的方法中
resolveThen = typeof resolveThen === 'function' ? resolveThen : function(v) {return v};
rejectThen = typeof rejectThen === 'function' ? rejectThen : function(r) {return r};
//返回的都是promise对象,这样就可以保证链式调用了
switch(this.status){
case PENDING:
return new Promise((resolve,reject)=>{
const onFullFilled = () => {
const result = resolveThen(this.data);//这里调用外部then的resolveThen方法,将值传回去
//如果返回值是promise对象,执行then方法,取它的结果作为新的promise实例的结果,因为this.data会重新赋值
result instanceof Promise && result.then(resolve,reject);
}
const onRejected = ()=>{
const result = rejectThen(this.data);
result instanceof Promise && result.then(resolve,reject);
}
this.defercb.push({onFullFilled,onRejected});
});
break;
case FULLFILLED:
return new Promise((resolve,reject)=>{
const result = resolveThen(this.data);
result instanceof Promise && result.then(resolve,reject);
resolve(result);
})
break;
case REJECTED:
return new Promise((resolve,reject)=>{
const result = rejectThen(this.data);
result instanceof Promise && result.then(resolve,reject);
reject(result)
})
break;
}
}
}运行下面的例子 new Promise((resolve, reject) => {
setTimeout(() => {
resolve(1);
}, 1000);
}).then((res2) => {
console.log(res2);
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(2);
}, 1000);
});
}).then((res3) => {
console.log(res3);
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(3);
}, 1000);
});
}).then((res4) => {
console.log(res4);
});控制台打印 new Promise((resolve) => {
resolve();
})
.then(() => {
console.log('1');
})
.then(() => {
console.log('2');
});
console.log('3');并没有像预想中输出3,1,2,而是输出了1,2,3,原因就是因为我们的这个Promise是在主线程中,没有在下一个任务队列中,可以加上settimeout解决这个问题,不过这也只是为了让我们更好理解执行顺序而已,然而实际上是promise是属于微任务中的,而settimeout是属于宏任务,还是不太一样的 以上就是promise对象的深入解析(附示例)的详细内容,更多请关注php中文网其它相关文章! 网站建设是一个广义的术语,涵盖了许多不同的技能和学科中所使用的生产和维护的网站。 |
温馨提示:喜欢本站的话,请收藏一下本站!