请教 JS 中有关 Promise 和回调函数的写法问题

2024-06-12 23:30:27 +08:00
 wuoty

在网上浏览的时候看到了下面的一种写法,可以通过新建一个 Promise 对象,在 Promise 对象中绑定回调函数,并获取回调结果,类似与下面这种:


    const img = document.getElementById("bg");
    
    const message = () => {
      return new Promise((resolve, reject) => {
        img.onload = () => {
          resolve("Image loaded successfully"); // 返回回调函数的结果
        };
      });
    };

    const AsyncTest = async () => {
      try {
        const msg = await message();
        console.log(msg);
      } catch (error) {
        console.log(error);
      }
    };

上面的代码确实能够将回调函数的返回值作为 Promise 的调用结果返回。

随后突发奇想,用下面这种方式分别异步调用两次上面代码中的 AsyncTest 的函数:


    // 连续两次调用 AsyncTest 函数
    AsyncTest().then(() => {
      console.log("Async function executed");
    });
    AsyncTest().then(() => {
      console.log("Async function executed");
    });
    

结果发现虽然两次调用,但是只有一个调用有返回,个人的理解是:

这样是否就意味着,第一次的 Promise 始终没有完成,保存在栈空间中,并在 EventLoop 中循环等待 resolve 的调用。 在图片加载完成后拍了堆快照,发现堆中确实留下了一个 Promise 的空间:

请教一下,这是否意味着这块内存空间是否会始终被占用,以及利用 Promise 监听 onload 回调这种写法是否妥当?

3963 次点击
所在节点    JavaScript
28 条回复
amlee
2024-06-13 17:51:06 +08:00
真别 rxjs 一直说了,原生 api 就有解决方案,就是 addeventlister 添加事件触发函数,防止重复绑定,建议读读这篇

https://zh.javascript.info/introduction-browser-events#addeventlistener
enjoyCoding
2024-06-13 18:12:53 +08:00
这种带有副作用的函数(绑了时间没有解绑)调一次可以, 调两次不行. 因为元素是一个 onload 时间只会在第一次触发, 甚至如果不立刻调用都不会触发. 正常的操作应该写成无副作用的函数, 怎么改成无副作用的函数 每次都新建一个插入 body, 绑定有 addEvent 用完了解绑, 删除元素
Al0rid4l
2024-06-13 21:08:50 +08:00
@RedNax 理论上来讲一次性事件当然是可以, 不过个人觉得这个习惯不好, 比如写习惯了一下没注意结果什么事件都用 Promise, 或者同事看见了以为用 Promise 把事件转 awaitable 是正确操作, 把其他事件也跟着这么写, 都很容易埋坑
jerry4718
2024-06-14 00:07:50 +08:00
都是说的什么啊,问题明明出在 onload 被覆盖上面啊
jerry4718
2024-06-14 00:54:57 +08:00
抱歉,眼瞎了
我觉得用 Promise 来监听 onload 合不合理要分场景来说
如果 img 生命周期很短,比如说封装的工具函数,直接 create 一个 img ,在 onload 里面获取 blob 或者尺寸信息,这时候会不会被覆盖是可控的,个人认为也可以视作“小而美”的
但是如果生命周期比较长,emmmm ,那不好说
,有可能写出来的逻辑都不能符合预期,副作用这东西,要多讨厌有多讨厌
nexo
2024-06-14 02:29:17 +08:00
@lolizeppelin rx 是什么
xiyuesaves
2024-06-14 09:15:34 +08:00
RedNax
2024-06-15 00:05:29 +08:00
@Al0rid4l RxJs 固然方便,但传染性太强,等完全转 RxJs 了,坑就在复杂到爆的面条 RxJS 代码里了,反而更难调试。
我也倒不是反对 RxJs ,不少场景下还是有用的,但大多数情况下我是觉得太重了。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1049064

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX