深入聊聊asyncPromise

news/2024/12/17 13:24:31/文章来源:https://www.cnblogs.com/SuahiStudy/p/18612144

正文

最近在学习JavaScript里的async、await异步,对于其中的Promise状态以及背后的Js引擎实际运行状态不大理解且很感兴趣,因此花了一点时间仔细研究了一下。

从Example说起

const createImg = function (path) {return new Promise((resolve, reject) => {const img = document.createElement('img');img.src = path;img.classList.add('images');img.addEventListener('load', () => {imgContainer.append(img);resolve(img);});img.addEventListener('error', () => {reject(new Error('image has not found!'));});});
};const loadImg = async function(imgPath){const imgs = imgPath.map(async img => await renderImg(img));console.log(imgs);  // Question
}loadImg(['./img/img-1.jpg', './img/img-2.jpg', './img/img-3.jpg'])

其中imgPath是图片地址数组,loadImg是遍历渲染图片的异步函数,renderImg是在当前页面插入并渲染图片的一个异步函数。我的疑问从Question Line开始,为什么控制台打印出的是Promise < fulfilled: undefined>

async机制

我开始从async在Js引擎中的执行逻辑学起:async会开辟一个单独的协程,并且当执行到其中await行(前提是返回Promise)时,将await后表达式放入Web APIs后台运行。

遵循这个执行逻辑分析,loadImg首先开辟一个loadImg协程,并且在执行到imgPath.map(async img...)行时,单独为几个img异步函数分别开辟了协程,为方便后文称img1、img2、img3协程

image.png

图中箭头表示当前CALLSTACK中执行的是哪个协程的代码内容,由于await createImg(img)中createImg是一个返回Promise的异步函数,因此会把createImg放入Web APIs中,并立即返回一个Promise< pending >。

[!NOTE]

这里值得注意的是,createImg返回的Promise< pending>是返回在Img协程内部的,也就是说如果有一个变量可以接收,例如 const tmp = await createImg(img),则这个Promise是赋值给tmp的;但是async调用之后会立即返回一个Promise< pending >对象(后文详细描述为什么打印出来的是Promise< fulfilled: undefined >,与之不同)。

最终可以看见在LoadAll协程处返回了3个Promise< pending >对象,但是console.log出来的还是Promise< fulfilled: undefined>,很奇怪。

我反思可能有两个问题:

  1. createImg(img)的响应速度太快了,这导致在不同协程间切换的时候,已经fulfilled了;
  2. 又或者是async返回的永远都是Promise< fulfiiled>?
const loadAll = async function (ImgArr) {const imgs = ImgArr.map(async Img => {console.log('start rendering');await new Promise(resolve => setTimeout(resolve, 2000));await createImg(Img);console.log('end rendering');return Img;});console.log(imgs);
};

这次我在createImg前加了2s的阻塞,这样就能知道到底是谁的问题了。

image.png

结果还是Promise< fulfilled: [[value]]>? 实话说真有点懵了。
理性分析来说,Promise是即刻返回的,所以不存在看后续代码中是否能跑通,是否有bug等,所以理论上来说可以直接排除问题2,因为通常来说pending可以到fulfilled/reject两个状态
在我多次尝试之后,发现...

console控制台实时渲染

直接上结论:

Promise返回的就是Promise< pending>,也只能返回这个对象,而其中的fulfilled /reject状态是当async中的异步代码后台跑完后返回给console,并由console去动态渲染替换的

证据:

image.png

在阻塞的2s期间内点击控制台的Promise对象数组,可以看到在async整体代码没跑完的时候,每个Promise都是pending的状态,等2s阻塞期过后,由于createImg的速度很快,一下就可以由console完成由pending ->fulfilled状态的动态渲染替换。

问题

None

总结

至此破案,也让我更进一步的理解async、Promise、await的机制。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/854290.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[OS] 计算机资源虚拟化技术

1 定义:计算机资源虚拟化服务器虚拟化主要通过软件技术将物理服务器的硬件资源抽象化,创建多个独立的虚拟服务器环境。2 虚拟化技术方向 以下是一些常见的服务器虚拟化方式和工具: 基于hypervisor的虚拟化Hypervisor技术: 也称为虚拟机监视器(Virtual Machine Monitor,VMM…

C#调用Python代码的方式(二),以PaddleOCR-GUI为例

前言 前面介绍了在C#中使用Progress类调用Python脚本的方法,但是这种方法在需要频繁调用并且需要进行数据交互的场景效果并不好,因此今天分享的是C#调用Python代码的方式(二):使用pythonnet调用Python代码。 pythonnet介绍 Python.NET 是一个包,为 Python 程序员提供了与…

在线教育系统厂家电话

为了方便您直接对接相关业务,下面提供几个在线教育相关企业的联系电话,请自行选择合适的服务商联系。若想直接获取更多信息或定制化的产品方案,请拨打以下联系电话:- 顺企网在线教育直播软件开发平台联系人:张生;联系方式:电话 15989102540(说明您来自顺企网,可获得优…

如何解决Git合并冲突?

讲个故事先: 一个晴朗的日子,Alex 把远程版本库的修改拉到他的本地版本库。 他修改了名为 abc.txt 的文件,将其暂存(staged),提交(committed),最后推送(pushed)回远程版本库。 同时,Tina 不知道 Alex 对abc.txt文件的修改,在该文件的 相同区域 做了一些修改,并尝…

MongoDB备份脚本

#!/bin/bash #backup MongoDB #mongodump命令路径 DUMP=/home/mongodb/bin/mongodump #临时备份目录 OUT_DIR=/home/mongodb_bak/mongodb_bak_now #备份存放路径 TAR_DIR=/home/mongodb_bak/mongodb_bak_list #获取当前系统时间 DATE=`date +%Y_%m_%d` #数据库账号 DB_USER=roo…

SQL Server创建用户一直提示用户已存在的解决办法

背景:复制的老数据库,创建账号onlyread时,一直提示数据库里有这个用户名。报错如下:“用户、组或角色onlyread在当前数据库中已存在。”解决方法: 1. 查询数据库,是否有这个用户 -- 查询是否存在指定的用户、组或者角色 SELECT * FROM sys.database_principals WHERE na…

jquery目录树插件

file-explore是一款简单的jquery目录树插件。它使用嵌套的无序列表作为目录树的结构,结合font-awesome图标可以制作出非常漂亮的jquery目录树效果。在线预览 下载使用方法 在页面中引入file-explore.css和font-awesome文件,以及jquery和file-explore.js文件。<link rel=&…

SQL Server的数据库备份与还原

数据库备份分类 备份分类完全备份:(常用方式)备份整个数据库,包含用户表、系统表、索引、视图和存储过程等所有数据库对象。 因而,占用不少时间和空间,这种方式不建议太频繁,一般一周一次。差异备份:也叫增量备份。它不使用事务日志,相反,它使用整个数据库的一种新映…

vue-实现组件是否显示还是隐藏

比如我们在home页面需要这个标签在city页面不需要这个标签我们可以在router里面添加meta属性在需要的组件页面导入route实力获取meta属性的值

教育行业办公软件排行榜揭晓!J 人备考该选谁?

在教育领域,高效的办公软件对团队协作和个人学习意义重大。尤其对于 J 人,其偏好秩序与规划,可视化团队协作办公软件能助其在教育教培团队运作和个人公考备考中精准把控进程。本文将盘点 6 款此类软件,助力相关人士做出合适选择。 一、板栗看板 板栗看板是教育办公软件中的…

github克隆代码报错

报错一: git clone https://github.com/PanJiaChen/vue-admin-template.git报错 Cloning into vue-admin-template... fatal: unable to access https://github.com/PanJiaChen/vue-admin-template.git/: Failed to connect to github.com port 443 after 21219 ms: Timed out…

Vulnhub 靶场 DevGuru: 1

前期准备 靶机地址:https://www.vulnhub.com/entry/devguru-1,620/ kali攻击机IP:192.168.11.128 靶机IP:192.168.11.130 一、信息收集 1.使用nmap对目标靶机进行扫描开了 22、80、8585 端口。发现 git 目录,且提示做解析: 192.168.11.130 devguru.local 2. 80 端口发现用…