淘汰赛:在等待查询完成时加载页面
Posted
技术标签:
【中文标题】淘汰赛:在等待查询完成时加载页面【英文标题】:Knockout: Loading Page While Waiting for a Query to Finish 【发布时间】:2017-07-22 20:21:38 【问题描述】:总结:我有一个可观察的控制加载页面元素,该元素在长时间运行的查询期间隐藏所有内容。即使在查询之前更改了 observable,加载页面也不会显示。放置一个占位符 setTimeout 有效,但页面似乎在等待查询运行以更新页面。
编辑 3:我应该提到我在 Node.js 中这样做。
Edit2:我想要发生的事情:
1) 用户点击按钮。 2) 载入画面覆盖表格。 3) 计算运行 4) 加载屏幕消失,表格填充结果
目前正在发生的事情: 1) 用户点击按钮。 2) 计算运行时屏幕会冻结 3-4 秒。 3) 表格中填充了结果
说明我们的页面上有几个运行时间较长的查询(大约需要 3-4 秒),我们希望设置一个加载屏幕来隐藏控件并通知人们该页面正在运行。
这是我写的一个扩展器(在互联网的帮助下):
ko.bindingHandlers.Loading =
init: function (element)
$(element).append("<div id='loading_wrap' class='loader' style='height:100%; width:100%;text-align:center; margin-top: 20%'><img src='./resources/ajax-loader.gif'><br>Loading, please wait.</div>")
,
update: function (element, valueAccessor)
var isLoading = ko.utils.unwrapObservable(valueAccessor());
var $element = $(element);
var $children = $element.children(':not(.loader)');
var $loader = $(element).find('.loader');
if (isLoading)
$children.hide();
$loader.show();
else
$children.show();
$loader.hide();
我将 bindingHandler 附加到一个 div,其中包含我想要隐藏的结果,直到它们准备好:
<div class="row table__row" data-bind="Loading:isLoading">
我在运行查询之前设置了 this.isLoading(true),然后在查询之后将其设置回 false。以下内容不起作用:
this.load = _ =>
var _self = this
this.isLoading(true)
this.search()
this.isLoading(false)
但是,如果我设置了超时,加载页面会正确显示。
this.load = _ =>
var _self = this
this.isLoading(true)
setTimeout(function ()
_self.isLoading(false);
, 3000)
我也尝试了几种异步方法,但我对此没有很好的理解。那么,如何使加载页面在查询运行之前出现,然后在查询完成后消失呢?谢谢。
编辑: 对我们的搜索功能有一些要求。它看起来像这样(我们没有使用 Ajax)
this.search = async _ =>
//bunch of filters/calculations on large arrays
this.results(the results of our large calculations)
【问题讨论】:
您是否使用 ajax 进行查询?如果可以,你可以在 beforesend ajax 方法中设置它吗? 只说“……不行”有点太笼统了,冷你请提炼?如果您使用的是 ajax,请提供您的异步方法的代码。 感谢大家的快速回复:不,我们没有使用 Ajax,我有一个 javascript 函数可以进行一些计算。 (我不确定正确的术语是什么)。计算运行大约需要 3-4 秒。它看起来像this.search = _ => //bunch of filters on large arrays //calculations //set some observableArray values
【参考方案1】:
使用绑定处理程序并不是绝对必要的,因为您只能在一个方向上执行操作。
保持简单:
this.isLoading.subscribe(function(value)
... get elements
$children.toggle(!value);
$loader.show(value);
);
在您发表评论后,我相信您需要的只是在加载微调器显示后稍微推迟您长期运行的工作,类似这样:
this.isLoading(true);
setTimeout(function ()
this.search();
this.isLoading(false);
, 100);
这是一篇关于承诺和异步代码之间区别的精彩帖子:https://***.com/a/20930199/4845566
顺便说一句,这里是extenders 和binding handlers 的淘汰参考。
【讨论】:
感谢您的回复。我正在尝试使此加载屏幕也可用于其他页面,而不仅仅是我正在处理的页面。使用 bindingHandler 似乎可以很容易地附加到 DIV 上,但我也可以为扩展器做同样的事情? 恕我直言,如果您在一页中有多个加载微调器,那么您的方法会很棒,否则统一的方法是将加载包装器放在带有visible binding的标记中 顺便说一句,现在你的问题听起来完全不同了。你确定你的async
调用一个繁重的同步计算会像你期望的那样表现吗?我相信你无论如何都要等待异步调用中的同步阻塞计算完成......只是推迟了。我不清楚在这里使用async
应该是什么工作流程。你能解释一下吗?
搜索功能不必是异步的;我认为这就是我的加载屏幕出现所需要的。我只希望发生以下情况:1)用户点击按钮:2)加载屏幕出现覆盖表格:3)计算运行:4)计算完成,结果显示在表格上。所以,到目前为止发生的一切是:1)用户点击按钮。 2) 屏幕似乎冻结了 3-4 秒。 3) 表格填充
谢谢,已经结束了。目前,该功能的行为是:1)用户点击按钮 2)加载屏幕显示,旋转 gif 冻结。 3) 结果显示。但一个问题是它只能工作一次。然后,它回到旧的行为(没有加载屏幕,只是冻结直到结果显示)以上是关于淘汰赛:在等待查询完成时加载页面的主要内容,如果未能解决你的问题,请参考以下文章