在等待异步任务时永远循环?

时间:2015-04-07 07:09:33

标签: javascript web-worker

我想知道是否有办法让JavaScript在继续使用事件和循环之前等待一些可变长度的代码执行完成。在回答使用超时,回调或将其作为副本引用之前,请听我说。

我想向Web worker公开一个大型API。我希望这个API在某种意义上感觉“原生”,你可以使用getter访问每个成员,它从另一个线程获取信息。我最初的想法是编译API并在worker上重建整个对象。虽然这是有效的(并且是一个非常有趣的项目),但它在启动时很慢,并且如果没有在修改后再次发送给工作者,则无法显示对API的更改。观察者会解决部分问题,网络工作者可转移的对象可以解决所有问题,但它们尚未被广泛采用。

由于工作者往返调用在几毫秒内发生,我认为将线程停止几毫秒可能是一个好的解决方案。当然,我会考虑在呼叫时间过长的情况下终止,但我试图首先创建一个概念证明。

假设我想将api对象公开给worker。我会为self.api定义一个获取第一层属性的getter。然后每个属性都是另一个getter,并且该过程将继续,直到找到最终对象。

worker.js

self.addEventListener('message', function(event) {
    self.dataRecieved = true;
    self.data = event.data; // would actually build new getters here
});

Object.defineProperty(self, 'api', {
    get: function() {
        self.dataRecieved = false;
        self.postMessage('request api first-layer properties');
        while(!self.dataRecieved);
        return self.data; // whatever properties were received from host
    }
});

对于实验,我们将进行简单的往返,无需数据处理:

index.html(仅限JS部分)

var worker = new Worker("worker.js");
worker.onmessage = function() {
    worker.postMessage();
};

如果onmessage会中断循环,那么理论上该脚本应该可行。然后,工作人员可以动态访问window.document.body.style之类的对象。

我的问题实际上归结为:有没有办法保证事件会中断正在执行的代码块?

根据我对JavaScript事件的理解,我认为他们确实打断了当前的线程。是不是因为它一遍又一遍地执行一个空白的陈述?如果我生成了要执行的代码并继续执行该操作直到数据返回,该怎么办?

2 个答案:

答案 0 :(得分:0)

据我所知,JS中没有本地的东西可以做到这一点,但做类似的东西相对容易。我不久前为自己做了一个:https://github.com/xpy/whener/blob/master/whener.js

您可以像when( condition, callback )一样使用它,其中condition是一个在满足条件时应返回true的函数,callback是您当时要执行的函数。 / p>

答案 1 :(得分:0)

  

有没有办法保证事件会中断正在执行的代码块

正如@slebetman在评论中建议的那样,不,不是在浏览器的网络工作者中运行的Javascript(我可以想到一个可能的例外,见下面的建议3.)。

我的建议,按优先顺序递减:

  1. 放弃感受"本地" (或者可能"本地"可能是一个更好的术语)。像你提出的无限while循环这样的东西似乎也是Javascript提供的合作多任务环境的再次战斗,包括考虑单个网络工作者时。

    Javascript中的工作者之间的通信是异步的。也许它可能会失败,需要的时间不会超过几毫秒。我不确定你的用例是什么,但我的感觉是,当项目增长时,你可能想用这些毫秒来做其他事情。

    您可以更改已定义的属性以返回承诺,然后调用者将对响应执行.then以检索该值,就像任何其他异步API一样。

  2. Angular Protractor / Webdriver有一个API,它使用con trol flow来模拟使用promises的同步环境,总是传递promises。从https://stackoverflow.com/a/22697369/1319998

    获取代码
    browser.get(url);
    var title = browser.getTitle();
    expect(title).toEqual('My Title');
    

    据我了解,上面的每一行都为控制流添加了一个异步执行的承诺。 title实际上并不是标题,而是例如解析为标题的承诺。虽然它看起来像同步代码,但获取和测试都会在以后异步发生。

    您可以在Web worker中实现类似的功能。但是,我确实想知道是否值得付出努力。会有很多代码要做到这一点,我无法感觉到主要后果是使用它来编写代码会变得更难,而且不会更容易,因为会有很多隐藏行为。

  3. 在将XMLHttpRequest参数设置为false https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest#Parameters时,我所知道的唯一可以在Javascript中实现同步的是async。我想知道你是否可以提出某种方式来请求维护与主线程连接的服务器并沿此方式传递数据。我不得不说,我的直觉是,这是一个非常糟糕的想法,并且比从主线程请求数据要慢得多