javaScript 进阶之路 --- 《手写 Promise(中篇)》(一)

简介: javaScript 进阶之路 --- 《手写 Promise(中篇)》

image.png

手写 Promise(中篇)


前言: 阅读前需要拥有我们前面的五个支线任务的通关钥匙🔑 (0/5),

请完成你的登神长阶

本文紧接着前篇的主线任务,建议没看《前篇》的小伙伴先去看一下《前篇》再回过头看本篇内容。(没浏览过前面文章的小伙伴,建议在父母的陪同下完成阅读。📖)

一. 思考 MyPromise 现有的问题


如果你跟进了之前的文章,那么下面应该是你目前的代码

image.png

虽然现在好像我们的逻辑都在顺着一步一步走,但是这里面其实有一个非常严重的 bug 。我们暂时先不揭秘,反过来我们先思考一下🤔,在原生的 Promise 如果我们在构造器函数内多次调用 resolve 函数的话,它保存的值是会以哪次为准呢?

image.png

image.png

这里我们直接揭晓答案。结果是 Promise实例 只会保存第一次调用 resolve 函数保存的那个数据。

但是现在反过头来看看我们目前的逻辑。

image.png

在控制台输出的结果是:

image.png

造成这种情况的原因非常简单,因为按照上面的写法,我们相当于在 executor 里连续调用了三次 resolve 如下所示:

image.png

结果显而易见,它调用了三次,按照代码逻辑,它 result 前两次的值被覆盖了,它保存了最后一次调用 resolve 时存入的值。

这里的解决方法依旧非常简单,我们不需要借助其它东西,我想你也能大概猜出来。这里还是需要借助 #state 来判断我们是否继续执行过了 resolve

image.png

别忘了,我们在 constructor 刚刚执行的时候最先修改的就是 #state 的值,所以我们只需要在 resolvereject 函数执行之前,先判断当前 #state 是否不是 pending,如果不为 pendng 则说明之前已经执行过了,则直接返回,不进行任何其他操作。 reject 同理。我们再看一下控制台现在的的样子。

image.png

嗯,现在确实不会再执行后面的 resolve 函数了。

二. 异步数据的存储


写到这里你可能会发现,我们现在的 MyPromise 其实是一个假的,是一个只能保存同步数据的普通类而已。

因为我们现在的 Promise 是不能读取到异步存储到数据的。 这也是 Promise 的核心功能 保存异步数据 。因为我们向后端请求数据绝对不是一瞬间数据就过来的,而是会有时间的延迟,过一段时间才需要调用 resolve 去保存。

什么意思呢?我们先看原生的 Promise 如果使用异步代码执行 resolve 的话是什么情况。 我们在 executor 函数体内开启一个定时器,在一秒以后去执行 resolve 保存数据。

image.png

我们在控制台看一下输出结果:

41dfe2f1e44b4bd99f2e97bd459f1f1c_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.jpg

可以清楚的看到,我们在 then 方法过了一秒,成功读取到了 result 中的数据。

现在我们回过头看看我们的 MyPromise 是什么效果。

image.png

观察上面的代码,我们推算出在理想状态,控制台会输入一个数字 1。然而结果确实---控制台空空如也。

image.png

这是怎么回事呢?我们一步一步分析。

当我们的代码执行时,首先会去执行这一段代码。

image.png

根据前面的知识可以得出,我们的 executor 函数会马上开始执行。

image.png

紧接着就遇到 setTimeout 函数。经过前面的学习,我们知道 setTimeout 的回调函数会被放进宏任务队列,结果就是我们的 resolve 被放进了宏任务队列去乖乖排队去了,

根据从上往下的执行顺序,马上就会去执行 then 方法。

image.png

注意: 这时候我们需要去看 MyPromise 类里的执行情况,才能知道原因

image.png

当我们的 executor 执行后,我们的 this.resolve 会在一秒后才会执行,所以 state 的状态还是 pending。 而此时我们的 then 又是在主线程执行的代码。所以自然而然,then 函数不会有任何结果。

本着严谨的态度,我们进一步验证一下我们的推断是不是正确的。让我们在 then 方法执行的时候打印一下 this.state

image.png

看一下控制台:

image.png

果然是这个原因,那现在怎么办呢?🤔

相关文章
|
1月前
|
数据采集 Web App开发 JavaScript
JavaScript爬虫进阶攻略:从网页采集到数据可视化
JavaScript爬虫进阶攻略:从网页采集到数据可视化
|
1月前
|
前端开发 JavaScript
如何处理 JavaScript 中的异步操作和 Promise?
如何处理 JavaScript 中的异步操作和 Promise?
15 1
|
1月前
|
前端开发 JavaScript
在JavaScript中,什么是promise、怎么使用promise、怎么手写promise
在JavaScript中,什么是promise、怎么使用promise、怎么手写promise
25 4
|
1月前
|
前端开发 JavaScript 开发者
JavaScript 中的异步编程:Promise 和 Async/Await
在现代的 JavaScript 开发中,异步编程是至关重要的。本文将介绍 JavaScript 中的异步编程概念,重点讨论 Promise 和 Async/Await 这两种常见的处理异步操作的方法。通过本文的阐述,读者将能够更好地理解和应用这些技术,提高自己在 JavaScript 开发中处理异步任务的能力。
|
1月前
|
前端开发 JavaScript
js开发:请解释Promise是什么,以及它如何解决回调地狱(callback hell)问题。
Promise是JavaScript解决异步操作回调地狱的工具,代表未来可能完成的值。传统的回调函数嵌套导致代码难以维护,而Promise通过链式调用`.then()`和`.catch()`使异步流程清晰扁平。每个异步操作封装为Promise,成功时`.then()`传递结果,出错时`.catch()`捕获异常。ES6的`async/await`进一步简化Promise的使用,使异步代码更接近同步风格。
19 1
|
2月前
|
前端开发 JavaScript API
JavaScript学习笔记(一)promise与async
JavaScript学习笔记(一)promise与async
|
2月前
|
前端开发 JavaScript UED
JavaScript中的异步编程和Promise
【2月更文挑战第3天】在Web开发中,JavaScript是一门非常重要的编程语言,而异步编程是JavaScript中的一个关键概念。本文将介绍JavaScript中的异步编程特点,以及如何使用Promise来更加优雅地处理异步操作,帮助开发者更好地理解和应用这一技术。
17 3
|
2月前
|
前端开发 JavaScript 数据处理
JavaScript中的异步编程及Promise对象
【2月更文挑战第3天】 传统的JavaScript编程模式在处理异步任务时常常会导致回调地狱和代码可读性较差的问题,而Promise对象的引入为解决这一问题提供了一种优雅的解决方案。本文将介绍JavaScript中的异步编程方式以及Promise对象的使用方法和优势,帮助读者更好地理解和运用异步编程技术。
20 8
|
2月前
|
前端开发 JavaScript
JavaScript中的异步编程与Promise
【2月更文挑战第1天】在Web开发中,JavaScript是一种常用的编程语言,而异步编程是其重要特点之一。本文将介绍JavaScript中的异步编程机制,探讨Promise对象的使用以及如何通过Promise处理异步操作,帮助读者更好地理解和应用JavaScript异步编程技术。
|
2月前
|
前端开发 JavaScript
JavaScript中的异步编程及Promise的应用
在前端开发中,异步编程是常见的需求,而Promise作为一种解决异步操作的技术,具有很高的应用价值。本文将介绍JavaScript中的异步编程原理,并结合实际案例详细讲解Promise的使用方法及其在前端开发中的应用。
13 2