我是苗条的新手,我正在尝试使用 websocket 获取温度,下面是用于使用 websockets 获取温度的代码。
ws.js
const webSock = () => {
let socket = new WebSocket("ws://localhost:54321/webTest");
let temperature = 0;
const getTemperature = () => {
return temperature;
}
socket.onopen = function (e) {
console.log("[open] Connection established");
console.log("Sending to server");
};
socket.onmessage = function (event) {
var message = JSON.parse(event.data);
temperature = data.message;
console.log(temperature);
};
socket.onclose = function (event) {
console.log(event.reason);
};
socket.onerror = function (error) {
console.log(`[error] ${error.message}`);
};
const sendMessage = () => {
var msg = {
'data': 'hello'
};
console.log(msg);
socket.send(JSON.stringify(msg));
}
return {getTemperature};
};
export default webSock;
Run Code Online (Sandbox Code Playgroud)
下面是App.svelte上的代码
<script>
import WS from "./ws.js";
const ws = WS();
$: temperature = ws.getTemperature();
</script>
<main>
<h1>{temperature}</h1>
</main>
Run Code Online (Sandbox Code Playgroud)
网页显示零,这是初始值并且不会进一步更改,但是在 Web 浏览器的控制台中,由于控制台日志语句,我能够获得温度
请指出我解决这个问题的正确方向。
谢谢你
漂亮的小 ws 模块 :)
所以,问题是你的ws.getTemperature()方法不是被动的。因此,尽管您在反应式表达式中使用$:Svelte 不会知道值何时更改,因此它只会运行一次。
您不仅需要传播值,还需要传播更改。
在老式 JS 中,我们会通过回调来做到这一点。您可以像这样调整代码,例如:
let _callback
const getTemperature = callback => {
_callback = callback // <- save a callback for future change
callback(temperature)
}
socket.onmessage = function (event) {
var data = JSON.parse(event.data);
temperature = data.message;
console.log(temperature);
if (_callback) _callback(temperature)
};
Run Code Online (Sandbox Code Playgroud)
在您的 Svelte 组件中,您可以订阅此数据源:
<script>
import WS from "./ws.js";
const ws = WS();
let temperature
ws.getTemperature(value => {
temperature = value // <- Svelte will see that, it's reactive!
})
</script>
<main>
<h1>{temperature}</h1>
</main>
Run Code Online (Sandbox Code Playgroud)
此处将传播更改,因为我们将分配给组件的顶级变量。赋值 ( =) 在 Svelte 中用于通知值已更改。
此代码将适用于您想要做的事情。现在,在 Svelte 中,您可以使用商店。存储本质上是某种简化的流(或在 ES 中称为 Observable),即它们代表一个随时间变化的值。与我们的回调示例相同,除了它们提供了一些其他非常有用的工具(例如计算来自其他商店的派生值),以及 Svelte 组件中的巧妙语法。当您需要从普通 JS 源导入“反应性”时,Store 是惯用的 Svelte 方式。请参阅文档以获取完整参考。
下面是我们如何用 store 来重写我们的回调示例:
// writable are the simplest form of stores
import { writable } from 'svelte/store'
const webSock = () => {
let socket = new WebSocket("ws://localhost:54321/webTest");
// our temperature is now a store with initial value 0
const temperature = writable(0);
// now we don't need to change this function, the change will be propaged
// by the store itself
const getTemperature = () => {
return temperature;
}
socket.onmessage = function (event) {
var data = JSON.parse(event.data);
// temperature = data.message;
// we update the value of our (writable) store,
// this will propagate the change
temperature.set(data.message)
};
// ... rest of the code
return { getTemperature };
};
export default webSock;
Run Code Online (Sandbox Code Playgroud)
在你的 Svelte 组件中,你可以使用带有特殊$前缀语法的 store来访问store的值(因为temperature变量是对 store 本身的引用,它只是我们目的的一种手段,我们需要的结果是该值):
<script>
import WS from "./ws.js";
const ws = WS();
const temperature = we.getTemperature()
console.log(temperature) // log the store, for the fun
// but what we want is the value, that we access with the special $ syntax
$: temp = $temperature
// for debug: this will log the value every time it changes
$: console.log(temp)
</script>
<main>
<!-- you can use the $ prefixed value directly in the template -->
<!-- (so we actually don't need the reactive expression above, in this example) -->
<h1>{$temperature}</h1>
</main>
Run Code Online (Sandbox Code Playgroud)
所以,很好,我们的代码更精简了……但这还不是全部!Svelte store 还有一个非常方便的功能来处理资源的处理。也就是说,您打开了一个 WS:您需要在某一时刻关闭它。Svelte 商店可以提供帮助。
实际上,$我们上面看到的语法实际上会设置对商店的订阅。并且当组件被销毁时订阅将被取消。如果 store 被多个组件订阅,则 store 将仅在最后一个组件取消订阅时才会被释放(如果进行了新订阅,它将被重新初始化)。这对于管理代码中一次性物品的生命周期非常方便。
为了使用它,我们需要使用更高级的readable存储。这是您为此更新的示例:
import { readable } from 'svelte/store'
// a readable store with initial value 0
//
// we pass it a function; the first argument of the function will let us update
// the value when it changes
//
export const temperature = readable(0, set => {
// this function is called once, when the first subscriber to the store arrives
let socket = new WebSocket("ws://localhost:54321/webTest");
socket.onmessage = function (event) {
var data = JSON.parse(event.data);
// we're using the `set` function we've been provided to update the value
// of the store
set(data.message)
};
// ... the rest of your socket code
const dispose = () => {
socket.close()
}
// the function we return here will be called when the last subscriber
// unsubscribes from the store (hence there's 0 subscribers left)
return dispose
})
Run Code Online (Sandbox Code Playgroud)
消费者组件与我们上一个示例几乎没有变化。唯一的区别是我们获取 store 引用的方式(因为现在 store 是从 JS 模块导出的):
<script>
import { temperature } from './ws.js'
// log the value
$: console.log($temperature)
// draw the rest of the owl
</script>
...
Run Code Online (Sandbox Code Playgroud)
这里!现在您的整个 WS 逻辑可以封装在您的 JS 模块中。这有助于很好地分离关注点。您的 WS 生命周期也由 Svelte 自动管理!(我们已经涵盖了 75% 的商店主题......它们很有效,重点......而且很简单!)
注意我没有深入检查我从你的例子中粘贴的代码,似乎有一些小错误,但我相信你会明白一般的想法,你可以自己解决这些问题。
| 归档时间: |
|
| 查看次数: |
1540 次 |
| 最近记录: |