在knockoutjs-vewmodel的后台运行的Worker

A Worker running in the background for knockoutjs vewmodel

本文关键字:Worker 运行 后台 knockoutjs-vewmodel      更新时间:2023-09-26

我有一个用于knockoutjs组件的视图模型。在视图模型中,有一个执行数分钟的函数init()。因此,浏览器上组件的UI将冻结,直到init()完成执行为止。

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需要使用JQuery。如果我通过postMessage将JQuery(和其他几个JSON对象(传递给worker,比如:worker.postMessage($),那么我会得到错误:

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

知道如何让init()在后台运行以避免UI冻结吗?

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

self.executeAsync = function(func) {
      setTimeout(func, 0);
};
self.executeAsync(self.init);

您可以使用promise。

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

在使用jQuery时,让我们使用这个库。只需3步

  1. 创建一个延迟对象,如下所示:var deferred = $.Deferred();
  2. 从这个延迟返回一个promise,这样您就可以使用.then在promise被解析或拒绝时包含回调。例如:return deferred.promise();,或者,如果您返回和object,您可以作为该object的成员返回promise,以检查是否完成:return { ..., promise = deferred.promise()};
  3. 当您的代码成功或失败时,解决或拒绝您的承诺,如下所示:deferred.resolve();deferred.reject();

在您的情况下,在init()开始时创建一个deferred,当所有jQueryajax都完成时,解决promise,或者如果出现问题,则拒绝它。

关于Deferred功能的一些注意事项:

  1. 如果您解析(或拒绝(延迟传递的对象,您将接收该对象作为回调的参数
  2. 您可以返回一个包含在promise中的对象。例如,如果init()返回一个对象(例如实现API的对象(,则可以返回包装在promise中的对象,如下所示:return deferred.promise(retVal);
  3. jQuery promise的实现直到3.0版本才与promises/A+兼容。这与回调链中的链接和异常传播有关。对于这种情况,它不会影响你。同时,您可以使用其他promise库,如Q或rsvp,它们与promises/A+兼容,并实现更多功能
  4. 您可以使用deferred.notify来表示进度。然后可以指定progress回调

jQuery的Deferred对象的文档。

伪代码:

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函数的作用,因此不清楚当promise被解析时,您是否必须更新一些可观察性,或显示一些控件或其他什么。这取决于你。

注意:如果使用jQuery操作DOM对象,恐怕会出错:在使用knockout时,所有DOM操作都应该使用ko绑定来解决。混合使用这两种DOM操作方式很快就会变得麻烦。

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

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