Javascript Svelte tick()不强制更新变量

Javascript Svelte tick()不强制更新变量,javascript,svelte,Javascript,Svelte,我遇到了苗条的一个常见问题,但没有找到一个好的解决方案。我有一个函数,当按下组件中的按钮时调用,基本情况如下所示 <script> import tick from 'svelte' let x = 0; let y = 0; let z = 0; async function buttonHandler() { --- multiple computationally intensive loops that update the vars x,y,z

我遇到了苗条的一个常见问题,但没有找到一个好的解决方案。我有一个函数,当按下组件中的按钮时调用,基本情况如下所示

<script>
import tick from 'svelte'

let x = 0;
let y = 0;
let z = 0;
async function buttonHandler() {
     --- multiple computationally intensive loops 
        that update the vars x,y,z at different points ---
    e.g.
    for (a in arr) {

        x ++;
        await tick();
    }
}
</script>

<main>
    <button on:click={buttonHandler}>Click Me</button>
    <p>{x}</p>
    <p>{y}</p>
    <p>{z}</p>
</main>

这似乎不是一个好的解决方案,我觉得我肯定错过了什么。是否有其他人的勾号未按预期工作?

您可以使用更新后的
功能检查您是否按预期刷新

从'svelte'导入{tick,afterUpdate};
更新后(()=>{
//这应该记录多次,每次在勾号()之后的预期值更改一次
控制台日志(x,y,z);
})
我在REPL中尝试了您的代码,添加了基本循环,每100次循环更新一次,它看起来仍然是即时的,但日志显示它确实正确更新了。因此,
flush
不会像React(阻塞线程)一样触发新的渲染,相反,它有自己的批处理时间表。为了解决这个问题,并保持事情的反应,而不是看起来笨重,他们建议使用CSS动画来获得所需的平滑效果。CSS动画不会阻止主线程

“在Svelte中更新组件状态时,它不会更新DOM 立即。相反,它会等到下一个微任务,看看是否 需要应用任何其他更改,包括 其他组件。这样做可以避免不必要的工作,并允许 使用浏览器可以更有效地批处理内容。”

发件人:()[https://svelte.dev/tutorial/tick]

这就是为什么在你的例子中它看起来是即时的

您可以在这里看到他们是如何通过tween动画解决此问题的:

因此,它们使用不会减慢或阻止主线程的动画(如
setTimeout
setInterval
或dom渲染)来减慢速度

更新
这里有一个更好的例子:

“但是这仍然不起作用”到底发生了什么?@FelixKling和“tick()”在函数终止之前,网页上的值保持为0,只有在该函数终止后,网页上的值才会更新为最终总数。我需要的行为是在函数执行时在网页上显示单个增量,例如1->2->3->4与1->4。这可以通过“sleep()”解决方法实现。您能提供一个更准确的实际代码示例吗?请注意,
tick
不是svelte的默认导出。您需要使用
import{tick}from'svelte'
来导入它。我无法在REPL中复制确切的代码,因为它使用了一些REPL认为是无限循环的语句(但代码在我的机器上工作)。我是否丢失了你链接的REPL,对我来说,这两个按钮似乎做了相同的事情,所以不确定我丢失了什么。Tick import不是问题,只是为了演示的目的。更新了答案,这里的空间太小。我理解问题是Tick()由于某种原因无法“强制”强制发布微任务。使用tweened值不是一个解决方案,因为在函数完成执行之前,该值仍然不会更改,但最终会有平滑效果插值值,但在函数执行时网页上不会有反馈(这是我需要的)更新后的回答:我创建了一个更好的例子来说明我将如何解决您的问题:我无法直接测试更新后的例子,因为我现在在开发中处于领先地位,但更新后的演示表明辅助功能应该可以解决问题。
function sleep(millisec = 0) {
        return new Promise((resolve, reject) => {
        setTimeout(_ => resolve(), millisec);
        });
    };