深入聊聊async&Promise
正文
最近在学习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协程。

图中箭头表示当前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>,很奇怪。
我反思可能有两个问题:
- createImg(img)的响应速度太快了,这导致在不同协程间切换的时候,已经fulfilled了;
- 又或者是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的阻塞,这样就能知道到底是谁的问题了。

结果还是Promise< fulfilled: [[value]]>? 实话说真有点懵了。
理性分析来说,Promise是即刻返回的,所以不存在看后续代码中是否能跑通,是否有bug等,所以理论上来说可以直接排除问题2,因为通常来说pending可以到fulfilled/reject两个状态。
在我多次尝试之后,发现...
console控制台实时渲染
直接上结论:
Promise返回的就是Promise< pending>,也只能返回这个对象,而其中的fulfilled /reject状态是当async中的异步代码后台跑完后返回给console,并由console去动态渲染替换的。
证据:

在阻塞的2s期间内点击控制台的Promise对象数组,可以看到在async整体代码没跑完的时候,每个Promise都是pending的状态,等2s阻塞期过后,由于createImg的速度很快,一下就可以由console完成由pending ->fulfilled状态的动态渲染替换。
问题
None
总结
至此破案,也让我更进一步的理解async、Promise、await的机制。
深入聊聊async&Promise的更多相关文章
- async + promise 解决回调地狱
// 解决异步回调地狱的方案: async + promise async function writeFile() { // 打开文件 const fd = await new Promis ...
- react-redux: async promise
1.the simple sample action: 事实上,只是返回个一个至少包含type的对象{ },用于reducer接收. import {RECEIVE_DATA} from " ...
- JS异步事件顺序:setTimeout,async,promise
为什么最近更新那么频繁,还不是因为笔试的时候瞎了? 先说异步事件执行顺序的规则: 1. 定时器异步队列和promise队列不是同一队列,promise优先级高于setTimeout; 2. 创建pro ...
- promise async await使用
1.Promise (名字含义:promise为承诺,表示其他手段无法改变) Promise 对象代表一个异步操作,其不受外界影响,有三种状态: Pending(进行中.未完成的) Resolved( ...
- async/await 执行顺序详解
随着async/await正式纳入ES7标准,越来越多的人开始研究据说是异步编程终级解决方案的 async/await.但是很多人对这个方法中内部怎么执行的还不是很了解,本文是我看了一遍技术博客理解 ...
- 如何避免 async/await 地狱
简评:async/await 写着很爽,不过要注意这些问题. async/await 让我们摆脱了回调地狱,但是这又引入了 async/await 地狱的问题. 什么是 async/await 地狱 ...
- 如何避免 await/async 地狱
原文地址:How to escape async/await hell 译文出自:夜色镇歌的个人博客 async/await 把我们从回调地狱中解救了出来,但是如果滥用就会掉进 async/await ...
- 学JS的心路历程-Promise(三)
今天我们来说then一些特殊情况以及Promise.all()与Promise.race(). 我们都知道函式作为参数传入时,可以参照的方式传入,也能传入时执行拿回传值作使用: function us ...
- 异步编程的类型系统:promise & future & closure & observable----异步编程类型的结构和操作
异步编程类型的结构和操作. 上下文维护. A promise represents the eventual result of an asynchronous operation. The prim ...
- 前端er,你真的会用 async 吗?
async 异步函数 不完全使用攻略 前言 现在已经到 8012 年的尾声了,前端各方面的技术发展也层出不穷,VueConf TO 2018 大会 也发布了 Vue 3.0的计划.而在我们(我)的日常 ...
随机推荐
- 音视频入门-2-ffmpeg-Linux下编译浅析,推流拉流快速体验
下载ffmpeg http://ffmpeg.org/download.html 1 .2 两种方式可以下载, 皆可. 编译ffmpeg ./configure -prefix=/usr/loca ...
- MySQL 用户、权限管理,C/C++连接与使用
目录 用户 用户管理 查询所有用户 查看当前用户 查看当前连接数 创建用户 删除用户 修改密码规则 查看规则/策略 规则说明 临时设置 持久设置 修改密码 权限 数据库提供的 权限列表 查看权限 给用 ...
- WebRTC 初探
背景 我正在实现一个 FC 游戏网站, PC 用户仅需要配置键盘便能实现小伙伴们一起玩, 但是手机用户就比较麻烦了 传统的网页游戏都是通过 HTTP/WS 的方式实现联机, 对于服务器的负担还是比较重 ...
- SXYZ-7.4训练赛
今天这场比赛把人心态考崩溃了,只考100分钟,四道思考和算法题,旁边大佬开局5分钟秒T1,我30分钟打了个T1暴力.┭┮﹏┭┮,呜呜~.T2,T4根据题意暴力.T3人手模拟了一下,完全没有任何思路,放 ...
- 如何安装eNSP
如何安装eNSP? eNSP是需要三个插件进行辅助的,所以先下三个插件,最后在下eNSP 首先来看看Wireshark的安装 很简单,基本上就直接下一步就行 这里直接下一步 这里要注意,这些要么安装在 ...
- Word、Excel办公书的资源下载
我是清华社编辑,下载资源没有版权问题,可供读者个人学习用,但不允许商用. 微信扫描,清华社网盘,可转自己邮箱下载.安全,无风险. <Word/Excel/PPT 2019商务办公从入门到精通&g ...
- foobar2000 v2.1.3 汉化版(更新日期:2024.04.02)
foobar2000 v2.1.3 汉化版 -----------------------[软件截图]---------------------- -----------------------[软件 ...
- Android系统之System Server大纲
前言 System Server是android 基本服务的提供者,是android系统运行的最基本需求,所有server运行在一个叫system_process的进程中,system_process ...
- vue前端开发仿钉图系列(2)左侧图层列表的开发详解
项目开发前还是特别说明一下组件库的重要性,谢谢饿了么团队分享的element组件库,大大节省了页面的开发成本.左侧图层列表核心功能有1.根据图层类型展示点线面2.开关控制右侧地图上点线面的展示和隐藏3 ...
- URL是什么
URL是什么 URL(Uniform Resource Locator,统一资源定位器) URL的组成: 协议://{域名|主机名|IP}:端口/路径/文件名?参数#锚点 协议 Scheme/Prot ...