跑在knockoutjs vewmodel的背景中的工作者

时间:2015-10-08 04:18:05

标签: javascript html5 knockout.js web-worker

我有一个knockoutjs组件的viewmodel。在viewmodel中,有一个函数init()可以执行几分钟。因此,浏览器上组件的UI冻结,直到function myViewModel(){ self = this; self.x = ko.observable(0); self.y = ko.observableArray([]); self.z = ko.observable({}); self.init = function(){ //Need to use JQuery here //loading stuff from DB via JQuery ajax //assign retrieved data to x and y and z } } 完成执行。

init()

有没有办法在后台运行Worker

我查看了Worker在后​​台运行的可能性,但worker.postMessage($)需要使用JQuery。如果我通过postMessage将JQuery(以及其他几个JSON对象)传递给worker,如下所示:init(),那么我收到错误:

无法在'Worker'上执行'postMessage':无法克隆对象。

知道如何让self.executeAsync = function(func) { setTimeout(func, 0); }; self.executeAsync(self.init); 在后​​台运行以避免冻结用户界面吗?

我尝试了超时,如下所示,但UI仍然冻结:

Employee

2 个答案:

答案 0 :(得分:1)

你可以使用承诺。

至于评论,你的问题是你知道如何使用所有的ajax承诺,但你不知道如何实现自己的承诺。

当你使用jQuery时,让我们用这个库来做。这只是3个步骤

  1. 创建一个这样的延迟对象:var deferred = $.Deferred();
  2. 从此延迟中返回一个承诺,以便您可以在承诺解决或拒绝时使用.then包含回调。例如:return deferred.promise();或者,如果您要返回并且是对象,则可以将该承诺作为该对象的成员返回,以检查完成情况:return { ..., promise = deferred.promise()};
  3. 当您的代码成功或失败时,请解决或拒绝您的承诺,例如:deferred.resolve();deferred.reject();
  4. 在你的情况下,在init()的开头创建一个延迟,当所有的jQuery ajax都完成后,解决这个问题,或者如果出现问题就拒绝它。

    有关Deferred功能的一些说明:

    1. 如果您解决(或拒绝)延迟传递对象,您将收到该对象作为回调的参数
    2. 您可以返回包含在承诺中的对象。例如,如果您的init()返回一个对象(例如实现API的对象),您可以返回包含在这样的承诺中的对象:return deferred.promise(retVal);
    3. 在版本3.0之前,jQuery promises的实现不是Promises / A +兼容。这与回调链中的链接和异常传播有关。在这种情况下,它不会影响你。在此期间,您可以使用其他承诺库,例如Qrsvp,它们与Promises / A +兼容,并实现更多功能。
    4. 您可以使用deferred.notify表示进度。然后,您可以指定progress回调
    5. jQuery's Deferred object的文档。

      伪代码:

      init: function() {
        var deferred = $.Deferred();
        // run your stuff, for example with setTimeout() or setInterval()
        // so that the code follows running on the same line
        // eventually, your stuff will resolve or reject the deferred/promise
        return deferrer.promise();
      }
      

      然后你可以像往常一样使用你的init回调:init().then(...);

      由于您没有解释您的init函数的作用,因此不清楚是否必须更新某些observable,或者在解析promise时显示某些控件或其他内容。这取决于你。

      注意:如果你使用jQuery操作DOM对象,我担心你可能做错了什么:当使用knockout时,所有的DOM操作都应该用ko绑定来解决。混合两种DOM操作方式很快就会变得很麻烦

答案 1 :(得分:0)

您可以使用Worker将jQuery导入importScripts()脚本。

Worker脚本的顶部,只需添加importScripts('path/to/jQuery'),您就可以访问jQuery了。 importScripts函数是WorkerGlobalScope接口中的全局函数,因此您的所有工作者都应该可以访问它。