网站首页 > 博客文章 正文
承诺最悲哀的不在于无法兑现,而在没有兑现时对于彼此的伤害。如果上天能够给我一个再来一次的机会,我会把承诺和猫装进盒子里。 - 量子态的Promise
请注意上面这张图,Promise的那些事,将在这个图上缓缓展开。
译者术语解释
Promise:可以对比理解中文词语承诺,某些期望憧憬会发生的。一般都可实现,也会出现不能实现的。
Resolve:处理Promise。表明工作正常,当前Promise得到处理,会调用后续环节函数,并把处理的数据传过去。
Reject:拒绝Promise。表明有些异常或者条件没有达到,会调用拒绝函数,一般建议组装Error对象作为入参传递过去,并跳转到catch中运行。
原文比较长,所以这里会分成三部分来讲解:Promise、事件循环和异步。
你是否曾经不得不去处理那些...没有按照你预期运行的JS代码?也许是函数不可预知的随机执行了,或者是延迟运行了。这给了你一个机会来使用ES6引进的一个很酷的新功能:Promises!
我多年来的求知欲得到了回报,不眠之夜再次给了我制作动画的时间。是时候谈谈Promise了:你为什么要使用它们,它们是如何在“幕后”工作的,我们如何才能用最现代化的方式把它们写出来?
如果您还没有阅读我之前关于JavaScript事件循环的文章,那么先读一下,可能会很有用!这里我将再次介绍一下事件循环,针对调用堆栈、Web API和队列做一些简单介绍,但这次我们还将介绍一些额外的令人兴奋的特性。
如果你已经熟悉了Promise,这里有一些捷径可以帮你节省宝贵的滑动时间。
介绍
在编写JavaScript时,我们经常要处理依赖于其他任务的任务!假设我们获取一个图像,压缩它,然后使用滤镜,最后保存它。
我们需要做的第一件事,就是得到我们想要编辑的图像,getImage函数可以处理这件事!只有成功加载该图像后,我们才能将它传递给resizeImage函数。成功调整图像大小后,我们希望在applyFilter函数中对图像应用一个滤镜。在图像被压缩并且添加了一个滤镜之后,我们希望保存图像,并让用户知道一切都工作正常!
最后,我们可能会得到如下代码:
getImage('/image.png', (image, err) => {
if (err) throw new Error(err)
compressImage(image, (compressedImage, err) => {
if (err) throw new Error(err)
applyFilter(compressedImage, (filteredImage, err) => {
if (err) throw new Error(err)
saveImage(compressedImage, (res, err) => {
if (err) throw new Error(err)
console.log("Successfully saved image!")
})
})
})
})
嗯...注意到了吗?虽然...好吧,代码看起来不太好的样子。我们最终得到许多依赖于前一个回调函数的嵌套回调函数。这通常被称为回调地狱,因为我们最终会有大量的嵌套回调函数,这使得代码很难阅读!
幸运的是,我们现在有Promise来拯救我们!让我们来看看什么是Promise,以及在这种情况下它们是如何帮助我们的!
Promise语法
ES6引入了Promise。在许多教程中,您会看到如下内容:
“Promise是值的占位符,该值可以在将来某个时间处理或者拒绝”
嗯...这个解释,相当于没有解释。事实上,这只会让我觉得Promise是一个诡异的,不明确的,不可预测的魔法。让我们看看Promise到底是什么。
我们可以使用Promise构造函数来创建Promise,构造函数接受一个回调函数作为入参。超酷,让我们试试!
等等,哇,刚刚返回了什么玩意?
Promise是一个包含状态([[PromiseStatus]])和值([[PromiseValue]])的对象。在上面的例子中,您可以看到[[PromiseStatus]]的值是“pending”,[[PromiseValue]]的值是“undefined”。
别担心-您永远都不会与这个对象有什么交集,您甚至无法访问[[PromiseStatus]]和[[PromiseValue]]属性!但是,在使用Promise时,这些属性的值很重要。
PromiseStatus的值,也就是状态,可以是以下三个值之一:
? fulfilled:Promise已经得到处理了。一切都很顺利,在Promise中没有出现错误。
? rejected:Promise被拒绝了。啊,出了点问题...
? pending:Promise既没有处理,也没有被拒绝(还没有),Promise仍然在等待结果。
听起来不错,但Promise的状态什么时候是“pending”、“fulfilled”或者“rejected”呢?为什么status的地位如此重要?
在上面的例子中,我们仅仅将简单的回调函数 ()=>{} 传递给Promise构造函数。但是,这个回调函数实际上接收两个参数。第一个参数的值,通常称为resolve或res,是在Promise应当得到处理时调用的方法。第二个参数的值,通常称为reject或rej,是在Promise应该被拒绝、出现问题时调用的方法。
让我们看看,当调用resolve或reject方法时的输出信息!在示例中,res表示resolve方法,rej表示reject方法。
棒极了!我们终于知道如何摆脱“pending”状态和"undefined"值!如果调用resolve方法,promise的状态为“fulfilled”;如果调用rejected方法,则promise的状态为“rejected”。
Promise的值,即[[PromiseValue]]的值,是我们传递给resolved或rejected方法的参数的值。
有趣的是,我让 jakearchibald 校对这篇文章时,他实际上指出Chrome中有一个bug,当前显示的状态是“resolved”而不是“fulfilled”。多亏了Mathias Bynens,它在Canary中被修复了!
好了,现在我们知道了如何控制不明确的Promise对象。但是我们可以用它来做什么呢?
在介绍部分,我展示了一个例子,在这个例子中,我们获取一个图像,压缩它,应用一个滤镜,然后保存它!最终,这变成了一个嵌套的回调地狱。
幸运的是,Promise可以帮助我们解决这个问题!首先,让我们重写整个代码块,让每个函数返回一个Promise。
如果图像被加载并且一切正常,那么让我们用加载的图像来处理这个Promise!否则,如果在加载文件时某个地方出现了问题,让我们用发生的错误来拒绝Promise。
function getImage(file) {
return new Promise((res, rej) => {
try{
const data = readFile(file)
resolve(data)
} catch(err) {
reject(new Error(err))
}
})
}
让我们看看在终端运行时会发生什么!
酷!像我们预期的那样,返回了一个包含解析过的数据的Promise。
但是...现在怎么办?我们不关心整个承诺对象,我们只关心这个数据的值!幸运的是,有一些内置的方法可以获得Promise的值。对于Promise,我们可以附加3个方法:
.then(): 在处理Promise后调用。
.catch(): 在拒绝Promise后调用。
.finally(): 始终被调用,无论Promise得到处理还是被拒绝。
getImage(file)
.then(image => console.log(image))
.catch(error => console.log(error))
.finally(() => console.log("All done!"))
.then方法接收传递给resolve方法的值。
.catch方法接收传递给被reject方法的值。
最后,我们在没有获得整个Promise对象的情况下获取到了Promise处理的值!我们现在可以对这个值做任何事情。
小提示,如果你确定一个Promise总是会得到处理或者总是被拒绝,你可以使用Promise.resolve 或者 Promise.reject,并把您要拒绝或处理Promise的值传给它们!
在接下来的示例中会经常看到这种语法。
在getImage示例中,我们不得不嵌套多个回调来运行它们。幸运的是,.then处理程序可以在这一块帮助我们!
.then 回调本身返回的结果就是一个Promise值,这意味着我们可以链接任意多个.then:前一个then回调的结果将作为参数传递给下一个then回调!
在getImage示例中,我们可以将多个then回调链接起来,以便将处理后的图像传递给下一个函数!这样我们最终得到了一个干净的then链,而不是多个回调的嵌套。
getImage('./image.png')
.then(image => compressImage(image))
.then(compressedImage => applyFilter(compressedImage))
.then(filteredImage => saveImage(filteredImage))
.then(res => console.log("Successfully saved image!"))
.catch(err => throw new Error(err))
完美!这个语法看起来已经比嵌套回调好多了。
翻译来源:https://dev.to/lydiahallie/javascript-visualized-promises-async-await-5gke#tasks
猜你喜欢
- 2024-10-11 JavaScript,ES6,Promise对象,异步编程的一种解决方案,代码
- 2024-10-11 使用 Matter.js 创建物理模拟:牛顿摆
- 2024-10-11 一首歌带你搞懂Promise(歌曲promise)
- 2024-10-11 如何用Vue3和p5.js绘制一个交互式波浪图
- 2024-10-11 IT技术栈:Javascript中Promise的pending、fulfilled和rejected
- 2024-10-11 Node.js中的Promise:回调的替代方案
- 2024-10-11 我终于真正理解 Promise 了!(promise 的理解)
- 2024-10-11 探究JS中Promise函数then的奥秘(js中promise什么意思)
- 2024-10-11 关于js中的promise,与其说是一种语法还不如说是一种思想!
- 2024-10-11 前端-JavaScript异步编程中的Promise
你 发表评论:
欢迎- 最近发表
-
- 给3D Slicer添加Python第三方插件库
- Python自动化——pytest常用插件详解
- Pycharm下安装MicroPython Tools插件(ESP32开发板)
- IntelliJ IDEA 2025.1.3 发布(idea 2020)
- IDEA+Continue插件+DeepSeek:开发者效率飙升的「三体组合」!
- Cursor:提升Python开发效率的必备IDE及插件安装指南
- 日本旅行时想借厕所、买香烟怎么办?便利商店里能解决大问题!
- 11天!日本史上最长黄金周来了!旅游万金句总结!
- 北川景子&DAIGO缘定1.11 召开记者会宣布结婚
- PIKO‘PPAP’ 洗脑歌登上美国告示牌
- 标签列表
-
- ifneq (61)
- messagesource (56)
- aspose.pdf破解版 (56)
- promise.race (63)
- 2019cad序列号和密钥激活码 (62)
- window.performance (66)
- qt删除文件夹 (72)
- mysqlcaching_sha2_password (64)
- ubuntu升级gcc (58)
- nacos启动失败 (64)
- ssh-add (70)
- jwt漏洞 (58)
- macos14下载 (58)
- yarnnode (62)
- abstractqueuedsynchronizer (64)
- source~/.bashrc没有那个文件或目录 (65)
- springboot整合activiti工作流 (70)
- jmeter插件下载 (61)
- 抓包分析 (60)
- idea创建mavenweb项目 (65)
- vue回到顶部 (57)
- qcombobox样式表 (68)
- vue数组concat (56)
- tomcatundertow (58)
- pastemac (61)
本文暂时没有评论,来添加一个吧(●'◡'●)