# 如何正确监听 post-stream 更新

**URL:** https://meta.discourse.org/t/how-to-correctly-listen-on-post-stream-update/203629
**Category:** Development
**Created:** [2021年九月15日 12:18 UTC](https://meta.discourse.org/t/how-to-correctly-listen-on-post-stream-update/203629 "2021-09-15T12:18:07Z")
**Posts on this page:** 7
**Page:** 1

<div class="post-metadata">

### Author: ![Ilia](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/ilia/32/227945_2.png) [@Ilia](https://meta.discourse.org/u/Ilia)
#### Post date: [2021年九月15日 12:18 UTC](https://meta.discourse.org/t/how-to-correctly-listen-on-post-stream-update/203629/1 "2021-09-15T12:18:07Z")

</div>

你好，

我正在尝试在页面添加更多内容时（例如长帖子）运行一个自定义函数，使用的是以下 API：

```plaintext
api.onAppEvent('post-stream:refresh', () => {
       console.log('页面已添加新内容...');
});

```

但上述方法并未生效。我哪里做错了？正确的做法应该是什么？

---

<div class="post-metadata">

### Author: ![david](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/david/32/157490_2.png) [@david](https://meta.discourse.org/u/david)
#### Post date: [2021年九月15日 12:28 UTC](https://meta.discourse.org/t/how-to-correctly-listen-on-post-stream-update/203629/2 "2021-09-15T12:28:43Z")

</div>

您能多分享一些您想要实现的目标吗？有几种不同的 API 允许您在渲染时修改帖子内容。其中最常用的是 `api.decorateCookedElement`。

---

<div class="post-metadata">

### Author: ![Ilia](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/ilia/32/227945_2.png) [@Ilia](https://meta.discourse.org/u/Ilia)
#### Post date: [2021年九月15日 12:37 UTC](https://meta.discourse.org/t/how-to-correctly-listen-on-post-stream-update/203629/3 "2021-09-15T12:37:16Z")

</div>

事实上，我刚刚意识到，我需要在添加到 DOM 的帖子内容上运行该函数。

我实际上是在重新实现 **`addPosterIcon`** API，因为我的版本需要包含自定义 HTML。除了长页面滚动时的问题外，其他功能都已实现并正常运行。

我试图在发布者用户名旁边添加一个图标，该图标会触发一个自定义事件。唯一的问题是，当 DOM 发生变化时，该图标尚未被添加。

---

<div class="post-metadata">

### Author: ![Ilia](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/ilia/32/227945_2.png) [@Ilia](https://meta.discourse.org/u/Ilia)
#### Post date: [2021年九月15日 13:14 UTC](https://meta.discourse.org/t/how-to-correctly-listen-on-post-stream-update/203629/4 "2021-09-15T13:14:51Z")

</div>

> [@david](#):
>
> 最常见的是 `api.decorateCookedElement`

这个方法的问题在于它会同时触发多个已渲染对象，因此更倾向于使用 ID（以避免内存泄漏），而这并不是我需要的。对我来说，如果能等到_所有_元素渲染完成后再触发一个事件就完美了。我有个想法可以实现这一点，但使用 Discourse API 是否有更合适的方法呢？

---

<div class="post-metadata">

### Author: ![david](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/david/32/157490_2.png) [@david](https://meta.discourse.org/u/david)
#### Post date: [2021年九月15日 13:21 UTC](https://meta.discourse.org/t/how-to-correctly-listen-on-post-stream-update/203629/5 "2021-09-15T13:21:46Z")

</div>

`decorateCookedElement` API 会在每次渲染帖子时触发一次。回调函数会接收包含帖子内容的 DOM 元素。其设计初衷是让你仅修改传入的元素，而不影响页面上的其他部分。

但由于你希望对帖子内容周围的元数据进行修改，`decorateCookedElement` 可能并不是最佳选择。

> [@Ilia](#):
>
> 我实际上是在重新实现 **`addPosterIcon`** API

那么，最好的办法可能是查看 `addPosterIcon` API 的实现方式：

> <https://github.com/discourse/discourse/blob/f3273bd43ea1ea8bd9b83b88cf4ff40a8d0327f4/app/assets/javascripts/discourse/app/lib/plugin-api.js#L347-L386>

其底层实现是对 `api.decorateWidget` 函数的调用。你可以自行调用该函数，并让其渲染原始 HTML。如需了解更多关于 `decorateWidget` API 的信息，可以查看 [https://meta.discourse.org/t/developer-s-guide-to-discourse-themes/93648#heading--4-c-6](https://meta.discourse.org/t/developer-s-guide-to-discourse-themes/93648#heading--4-c-6)。

---

<div class="post-metadata">

### Author: ![Ilia](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/ilia/32/227945_2.png) [@Ilia](https://meta.discourse.org/u/Ilia)
#### Post date: [2021年九月15日 16:53 UTC](https://meta.discourse.org/t/how-to-correctly-listen-on-post-stream-update/203629/6 "2021-09-15T16:53:52Z")

</div>

对我来说，让 **`decorateCookedElement`** 仅针对特定类型执行一次，并在所有烹饪内容就绪时触发，解决方案非常简单，如下所示：

```JavaScript
<script type="text/discourse-plugin" version="0.11">
  api.decorateCookedElement((callback, opts) => {
      if(opts?.widget?.dirtyKeys?.name === 'post-stream') {
          if(this?.cooking) clearTimeout(this.cooking);
          this.cooking = setTimeout(() => {
              console.log('All cooking is done, update new content..');
          });
      }
  });
</script>

```

如果这段代码有任何错误或潜在问题，请指正。

---

<div class="post-metadata">

### Author: ![Thorsten](https://avatars.discourse-cdn.com/v4/letter/t/d2c977/32.png) [@Thorsten](https://meta.discourse.org/u/Thorsten)
#### Post date: [2025年十二月10日 17:31 UTC](https://meta.discourse.org/t/how-to-correctly-listen-on-post-stream-update/203629/7 "2025-12-10T17:31:27Z")

</div>

抱歉在这个旧主题中添加一个问题。

我们之前使用上述代码（decorateCookedElement）在渲染附加帖子时调用一个简短的脚本函数。

使用 Glimmer 帖子流时，此代码无法正常工作。我们在开发者控制台中收到以下消息：

在使用 Glimmer 帖子流调用 `api.decorateCookedElement` 时，访问 `helper.widget` 不受支持，并可能产生意外结果。

因此，脚本函数未执行。

对于 Glimmer 帖子流，我们是否有相应的功能可以使用？

提前感谢您提供的任何有关调整我们编码的信息。
