查看原文
其他

在互联网计算机上创建投票容器智能合约

Dfifans Internet Computer 2023-05-02


一些用例需要前端 dapp 重复调用部署在互联网计算机区块链上的功能,每次调用之间有固定的时间延迟,例如,在 Papyrs(一个 Web3 博客平台)中没有保存按钮,用户的每次编辑都会自动保存在后端。
同样,另一个应用程序可能需要从服务器推送信息而不是被查询 - 例如,使用 web 套接字来实现聊天,但容器智能合约尚不支持此类协议或功能。
我通过创建 cronjob 来解决这两个问题,它在我的前端 dapp 中运行 - 即在浏览器中。
虽然并非所有这些功能都会降低 UI 的性能,但我喜欢谨慎行事,这就是为什么我总是把这些调度器的工作交给 Web workers。
在本文中,我将向您展示如何实现这样的解决方案(示例 GitHub 存储库如下)。
Web workers?
如果您不熟悉 Web workers,您可能会问自己它们是什么,我建议您查看 MDN 文档以了解所有详细信息,但总而言之,Web Workers 是在浏览器的后台线程中运行脚本的一种简单方法。
它们可以运行 JavaScript 并执行 HTTP 调用,但它们不能访问本地存储,也不能直接修改 DOM - 也就是说,你不能修改 Web worker 中的状态并期望 UI 会自动重新渲染,UI(窗口)和工作人员是分开的,你可以把它想象成嵌入 iframe 造成的分离。
简介
我打算展示的解决方案将工作从 UI 推迟到 Web workers,当应用程序启动时,它会初始化并启动轮询,它负责重复查询 IC,最终,为了在 UI 中呈现结果,后端线程将数据传输到浏览器的窗口。


因此,本教程涵盖以下步骤:
  • 设置并启动一个 Web worker;
  • 在 Worker 中使用 agent-js 来获取身份;
  • 调用 IC;
  • 将结果传输到 UI。

1. 设置一个 Web worker
对于本教程,我将使用 vanilla JavaScript,因为当您使用 dfx 或 npm init ic 创建一个新的示例应用程序时,结果是一个准系统前端应用程序。
但我支持你,我是 Web workers 的超级粉丝,我发布了各种教程,展示了如何为各种框架设置这些。
  • SvelteKit
  • Angular
  • Stencil

我还写了一篇关于 React 集成的文章,但它有点过时了,如果你使用 Webpack,最好遵循这篇文章。
因此,假设您还初始化了一个示例应用程序以遵循本教程,我们可以从在一个新文件中创建工作程序开始 - 例如,src/myapp_frontend/src/worker.js


在上面的代码片段中,此时 Worker 只是侦听消息并将这些消息打印到控制台。
在 UI 方面,我们声明了两个元素,一个 button 使用互联网身份登录,一个 textarea 最终呈现我们正在投票的结果。


我们不是绝对需要登录来使用 Web worker 查询 IC 或一般来说,但这可能是一个常见的用例,这就是为什么这篇文章也展示了它。
一旦 HTML 文档被完全解析,我们将一个 click 事件附加到执行使用 II 登录的按钮。


为了设置和启动 Worker,我们添加了一个额外的函数来创建一个 Worker 对象,声明一个用于接收结果的侦听器,并将来自 UI 的消息发布到 Worker 以启动轮询。


如果我们将解决方案部署到本地模拟网络,我们应该能够登录,并且当 dapp 启动时,Worker 应该打印“启动”消息。



2. 在 Worker 中使用 agent-js 获取身份
当我实现这种类型的 cronjob 时,我喜欢同时提供“开始”和“停止”选项,在这个特定的示例中,我们不会使用“停止”功能,但是当从组件创建工作器时它会特别有用,它可用于在组件卸载时停止计时器。


“start” 方法实例化了一个 setInterval,它将重复调用查询 IC 的函数,在这个特定的函数中,我们使用 agent-js 创建了一个身份验证客户端,以便在登录时检索用户的身份。
虽然初始化看起来与我们通常在 UI 端所做的相似(感谢 Sea Snake 在 Discord 上对此的输入),但重要的是要注意必须禁用客户端的“空闲管理器”功能。
此功能通过观察 window 事件来检测用户的不活动,Web worker 无法读取此类对象,而不是禁用这些功能,将导致错误。


3. 调用 IC
由于与上一章相同的限制,我们必须提供一个 host 信息来创建一个调用后端的 actor。
此外,由于 dfx 自动生成的声明包含一个仅设计用于 UI 端的默认 actor,因此我们必须将初始化 actor 的函数以及容器 ID 常量复制到我们的 Worker 或专用文件中。


一旦复制,我们就实例化 actor 并有效地执行调用。


要在浏览器中加载 Web worker 并在开发中获取根密钥,我们必须访问本地服务器并为主机提供容器 ID 作为子域(不是查询参数)。
对于生产,主机参数可以替换为 https://ic0.app,无论您的前端和后端有效 URL 是什么,这都能奏效。
与此解决方案不严格相关,这里是被调用的后端代码 - 即 greet 我为演示目的而实现的函数。


这是一个简单的更新方法,它增加一个计数器并返回 “Hello”,作为文本的调用者主体 ID 和增加的值。
4. 将结果传输到 UI
现在我们已经从 IC 获得了数据,我们可以应用这些数据来重新渲染 UI,由于 Worker 本身不能这样做,我们在 postMessage 的帮助下将数据传输到视图。


在第一章中,我们已经为从 Worker 接收到的消息声明了一个监听器,因此,为了最终确定解决方案,我们处理数据并更新 DOM。


上面的代码片段将数据(worker 提供的结果、后端返回的数据)附加到 textarea,如果我们部署到本地模拟 IC 并在浏览器中打开 dapp,我们应该注意到每两秒就会向元素添加一次文本。


总结
感谢 Web worker,我们可以在不影响 dapp 前端性能的情况下轮询互联网计算机,我爱它!
您将在我在 GitHub 上共享的示例存储库中找到此解决方案:
  • github.com/peterpeterparker/icwebworker

更多冒险,请在 Twitter(@daviddalbusco)上关注我。


作者:David Dal Busco翻译:Catherine

-              -


DFINITY - 如何杜绝区块链黑客

燃烧的 Cycles 描绘的互联网计算机生态系统增长

让我们发展互联网计算机网络:为什么和如何,以及一般更新





你关心的 IC 内容
技术进展 | 项目信息 | 全球活动


长按关注 IC 微信公众号

随时答疑解惑


*添加小助手微信 comiocn 进交流社群


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存