【发布时间】:2021-08-23 09:25:04
【问题描述】:
我正在使用带有 webpacker 的标准 Rails 6 设置。我正在为 JavaScript 使用 Stimulus,但这并不重要。
对于我的应用程序,我有一个计时器,即使浏览器选项卡未处于活动状态,它也需要继续运行。由于似乎setInterval 可以在选项卡未处于活动状态时停止,因此我潜心编写一个网络工作者。我读过this question,但它的解决方案似乎不适用于现代 Rails。
我希望我可以通过我的 Stimulus 控制器来处理这一切,但我的理解是 web worker 文件需要分开,所以我试图弄清楚如何正确加载它。
我为工人创建了一个文件timer.js。我应该把这个文件放在哪里,我如何引用它的 URL 以便将它作为工作人员启动?
- 我需要能够在我的一个视图 ERB 文件中呈现其 URL,以便我可以将其 URL 传递给 Stimulus 控制器,然后使用
new Worker(theUrl)启动工作程序。但是,<%= javascript_path(...) %>似乎仅适用于资产管道。 - 我想在我的工作文件中使用
import Rails from "@rails/ujs",这样我就可以使用它轻松地发出 AJAX POST 请求,所以我认为工作文件需要以某种方式与 webpack 绑定。
目前我刚刚把它放在public/timer.js,但我在加载时在浏览器控制台中收到错误,所以我认为我做错了:
SyntaxError: import declarations may only appear at top level of a module
在 Rails 6 中加载 Web Worker 的正确方法是什么?
timer.js
这是工作文件的内容,以防万一。 (我知道这很粗糙;这只是一个草稿。)
import Rails from "@rails/ujs";
let timerInterval = null;
let timeRemaining = null;
let postFailures = 0;
let postUrl = null;
function finishActivity() {
Rails.ajax({
type: "POST",
url: postUrl,
success: () => {
postFailures = 0;
},
error: () => {
postFailures++;
if (postFailures < 5) {
setTimeout(finishActivity, 1000);
} else {
alert("Error.");
}
},
});
}
self.addEventListener("message", (event) => {
if (event.data.timeRemaining) {
timeRemaining = event.data.timeRemaining;
if (timerInterval) clearInterval(timerInterval);
timerInterval = setInterval(() => {
if (timeRemaining > 0) {
timeRemaining = timeRemaining - 0.01;
postMessage({ timeRemaining: timeRemaining });
} else {
timerInterval = null;
clearInterval(timerInterval);
finishActivity();
}
}, 10);
}
if (event.data.postUrl) {
postUrl = event.data.postUrl;
}
}, false);
【问题讨论】:
-
Webpacker 不会通过 ERB 传递 JS 文件。虽然您可以使用 erb-loader 执行此操作,但重新考虑您的设计并使用附加到元素或 ajax 调用的数据属性将数据从服务器传递到客户端可能是一个更好的主意。在 JS 资产中使用 ERB 通常是一个很好的方法,因为它是在部署时而不是运行时评估的。
-
@max 这是很好的信息。但是,我不需要在这里使用 erb,如果不清楚,抱歉。我实际上是使用数据属性在客户端和服务器之间传递数据(通过刺激)。但我的理解是我的JS需要运行
new Worker(urlOfJavaScriptFile)来启动worker,而当文件由webpacker处理时我不知道如何获取该URL。而且我认为我的文件需要由 webpacker 处理,所以我可以打电话给import Rails from "@rails/ujs"。
标签: javascript ruby-on-rails web-worker webpacker stimulusjs