promise对象的深入解析(附示例)
本篇文章给大家带来的内容是关于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); });
控制台打印
1
...1s later
2
先分析下上面这段代码,先提出几个问题
1.第一段resolve和reject都有,但是只输出了1,为什么?
2.then里的res是如何取到resolve中的值的?
3.promise是如何做到链式调用的?
状态机
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); });
控制台打印
...1s later
1
...1s later
2
...1s later
3
说明上面的实现是没有问题的
不过还有一个问题,就是事件循环的顺序问题,比如执行下面的代码
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中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

热门话题

WebSocket与JavaScript:实现实时监控系统的关键技术引言:随着互联网技术的快速发展,实时监控系统在各个领域中得到了广泛的应用。而实现实时监控的关键技术之一就是WebSocket与JavaScript的结合使用。本文将介绍WebSocket与JavaScript在实时监控系统中的应用,并给出代码示例,详细解释其实现原理。一、WebSocket技

PHP与Vue:完美搭档的前端开发利器在当今互联网高速发展的时代,前端开发变得愈发重要。随着用户对网站和应用的体验要求越来越高,前端开发人员需要使用更加高效和灵活的工具来创建响应式和交互式的界面。PHP和Vue.js作为前端开发领域的两个重要技术,搭配起来可以称得上是完美的利器。本文将探讨PHP和Vue的结合,以及详细的代码示例,帮助读者更好地理解和应用这两

在前端开发面试中,常见问题涵盖广泛,包括HTML/CSS基础、JavaScript基础、框架和库、项目经验、算法和数据结构、性能优化、跨域请求、前端工程化、设计模式以及新技术和趋势。面试官的问题旨在评估候选人的技术技能、项目经验以及对行业趋势的理解。因此,应试者应充分准备这些方面,以展现自己的能力和专业知识。

JavaScript和WebSocket:打造高效的实时天气预报系统引言:如今,天气预报的准确性对于日常生活以及决策制定具有重要意义。随着技术的发展,我们可以通过实时获取天气数据来提供更准确可靠的天气预报。在本文中,我们将学习如何使用JavaScript和WebSocket技术,来构建一个高效的实时天气预报系统。本文将通过具体的代码示例来展示实现的过程。We

JavaScript教程:如何获取HTTP状态码,需要具体代码示例前言:在Web开发中,经常会涉及到与服务器进行数据交互的场景。在与服务器进行通信时,我们经常需要获取返回的HTTP状态码来判断操作是否成功,根据不同的状态码来进行相应的处理。本篇文章将教你如何使用JavaScript获取HTTP状态码,并提供一些实用的代码示例。使用XMLHttpRequest

Django是一个Python编写的web应用框架,它强调快速开发和干净方法。尽管Django是一个web框架,但是要回答Django是前端还是后端这个问题,需要深入理解前后端的概念。前端是指用户直接和交互的界面,后端是指服务器端的程序,他们通过HTTP协议进行数据的交互。在前端和后端分离的情况下,前后端程序可以独立开发,分别实现业务逻辑和交互效果,数据的交

Go语言作为一种快速、高效的编程语言,在后端开发领域广受欢迎。然而,很少有人将Go语言与前端开发联系起来。事实上,使用Go语言进行前端开发不仅可以提高效率,还能为开发者带来全新的视野。本文将探讨使用Go语言进行前端开发的可能性,并提供具体的代码示例,帮助读者更好地了解这一领域。在传统的前端开发中,通常会使用JavaScript、HTML和CSS来构建用户界面

Golang与前端技术结合:探讨Golang如何在前端领域发挥作用,需要具体代码示例随着互联网和移动应用的快速发展,前端技术也愈发重要。而在这个领域中,Golang作为一门强大的后端编程语言,也可以发挥重要作用。本文将探讨Golang如何与前端技术结合,以及通过具体的代码示例来展示其在前端领域的潜力。Golang在前端领域的作用作为一门高效、简洁且易于学习的
