首页 > 其他分享 >深入聊聊async&Promise

深入聊聊async&Promise

时间:2024-12-17 13:31:25浏览次数:5  
标签:console img await createImg Promise 聊聊 async

正文

最近在学习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的机制。

标签:console,img,await,createImg,Promise,聊聊,async
From: https://www.cnblogs.com/SuahiStudy/p/18612144

相关文章

  • .net core中异步async await
    基本原理async,await是C#语言中用于简化异步操作的语法糖,实际会由编译器将代码翻译生成状态机来执行异步操作。状态机是一种数学模型,用于描述一个系统在不同状态之间的转换行为。它由一组状态和一组转换组成,在特定的输入条件下,系统从一个状态转换到另一个状态。例如如下的异......
  • 你不知道的 async、await 魔鬼细节
    0、前言关于promise、async/await的使用相信很多小伙伴都比较熟悉了,但是提到事件循环机制输出结果类似的题目,你敢说都会?asyncfunctionasync1(){awaitnewPromise((resolve,reject)=>{resolve()})console.log('A')}async1()newPromi......
  • 请实现一个Promise.race
    Promise.race()是一个JavaScriptPromiseAPI的方法,它接收一个promise对象的集合(例如,一个数组)作为参数,并返回一个新的promise对象,这个新的promise会在输入的promise集合中的任何一个promise状态改变为完成(fulfilled)或拒绝(rejected)时,就立刻以同样的结果改变状态。以......
  • Promise和setTimeout执行先后有什么区别?
    在前端开发中,Promise和setTimeout都是处理异步操作的重要工具,但它们之间有一些关键的区别,这些区别会影响它们的执行顺序和如何处理异步逻辑。事件循环与任务队列:JavaScript运行在单线程环境中,通过事件循环(EventLoop)来处理同步和异步任务。同步任务直接执行,而异步任务会......
  • JavaScript是按顺序执行的吗?聊聊JavaScript中的变量提升
    作为一位前端开发者,我们经常会听到这么一句话:“JavaScript的执行是按照顺序自上而下依次执行的。”这句话说的并没有错。但是它似乎又好像不完全对。我们先来看以下这段代码。你觉得结果会输出什么?1showName()2console.log(myName)34varmyName='修谦'5functionshow......
  • promise有哪几种状态?是如何变化的?
    在前端开发中,Promise有三种状态:pending(等待):Promise初始化时的状态。既没有被fulfilled(成功),也没有被rejected(失败)。在这个状态下,Promise的then方法和catch方法都不会被执行。fulfilled(已完成):Promise的异步操作成功完成后的状态。这时,then方法......
  • 聊聊前端常见的数据加密 转载
    前言你是否有过这样的经历?在注册一个新网站时,需要填写个人信息,例如姓名、邮箱、手机号码,甚至身份证号码。你可能会担心,这些信息会被泄露,被不法分子利用。前端数据加密,就是解决这个问题的关键技术之一。它可以在数据传输到服务器之前,对其进行加密处理,即使数据被窃取,也无法被轻易......
  • 浅析 C# Async 和 Await 【代码之美系列】
    文章目录一、引言......
  • Uncaught (in promise) Error: Could not establish connection. Receiving end does
    1.问题描述在html调用indexUser.nickname的属性时,没重新启动项目直接查阅该index.html,出现了页面加载出来的一片空白的情况,去掉{{indexUser.nickname}}页面就正常2.问题分析这种情况是访问不到值(未定义或为空)3.解决方案写了一小段检查是否为未定义或者空的代码,随......
  • CloseableHttpAsyncClient使用代理问题记录
    目录场景背景问题解决过程解决方案总结场景背景项目A部署到现场后,甲方要求调用接口上传某些数据给他们。问题代码很快就开发完成了,但是领导要求必须想办法调用一次测试一次,而且现场没有测试环境(测试当生产用),只能本地使用VPN然后再调用接口测试。VPN本身很多坑就不说了,后面VP......