Javascript与VBA的DoEvents有什么相似之处吗?

时间:2015-07-15 19:24:06

标签: javascript jquery vba events

我的代码中有一个长时间运行的for循环,我想延迟循环来处理事件队列中的其他任务(比如按下按钮)。 javascript或JQuery有什么可以帮助我吗?基本上我正在尝试做类似延迟循环的事情(https://support.microsoft.com/en-us/kb/118468)。

5 个答案:

答案 0 :(得分:6)

如果您的应用程序确实需要长时间运行的JavaScript代码,那么处理它的最佳方法之一就是使用JavaScript web workers。 JavaScript代码通常在前台线程上运行,但是通过创建Web worker,您可以在后台线程上有效地保持长时间运行的进程,并且您的UI线程可以自由地响应用户输入。

例如,您可以像这样创建一个新工作者:

var myWorker = new Worker("worker.js");

然后您可以从主页面中的js向其发布消息,如下所示:

myWorker.postMessage([first.value,second.value]);
console.log('Message posted to worker');

并回复worker.js中的消息:

onmessage = function(e) {
  console.log('Message received from main script');
  var workerResult = 'Result: ' + (e.data[0] * e.data[1]);
  console.log('Posting message back to main script');
  postMessage(workerResult);
}

答案 1 :(得分:2)

您可以使用setTimeout:

setTimeout(function() { }, 3600);

3600这是以毫秒为单位的时间:

http://www.w3schools.com/jsref/met_win_settimeout.asp

答案 2 :(得分:2)

通过在ES6中引入生成器,您可以编写一个帮助器方法,使用yield来模拟DoEvents而不需要太多的语法开销:

doEventsOnYield(function*() {
    ... synchronous stuff ...

    yield;  // Pump the event loop. DoEvents() equivalent.

    ... synchronous stuff ...
});

这是辅助方法,它还将函数的完成/失败暴露为Promise:

function doEventsOnYield(generator) {
    return new Promise((resolve, reject) => {
        let g = generator();
        let advance = () => {
            try {
                let r = g.next();
                if (r.done) resolve();
            } catch (ex) {
                reject(ex);
            }
            setTimeout(advance, 0);
        };
        advance();
    });
}

请注意,此时,您可能需要通过ES6-to-ES5转换程序运行它,以便在常用浏览器上运行。

答案 3 :(得分:0)

没有与DoEvents完全等效的内容。关闭的是每次迭代使用setTimeout

(function next(i) {
    // exit condition
    if (i >= 10) {
        return;
    }

    // body of the for loop goes here

    // queue up the next iteration
    setTimeout(function () {
        // increment
        next(i + 1);
    }, 0);
})(0); // initial value of i

然而,这很少是一个很好的解决方案,在Web应用程序中几乎不需要。您可能会遇到一个您遗失的事件。你真正的问题是什么?

答案 4 :(得分:0)

以下是如何使用Yield作为DoEvents的直接替代品的测试示例。

(我已经使用过Web Worker,它很棒,但它远离DoEvents,几乎不可能访问全局变量)。这已经过格式化以便于理解,并试图显示所需的额外内容(使函数处理产量)可以被视为原始函数中的插入。 "产率"具有各种其他功能,但因此使用它,它几乎是DoEvents的直接替代品。



//'Replace DoEvents with Yield ( https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/yield )
var misc = 0; //'sample external var

function myfunction() { //'This is the beginning of your original function which is effectively replaced by a handler inserted as follows..
//'-----------------------------------Insert Handler..
  var obj = myfuncGen.next(); //'start it
  if (obj.done == false) {
    setTimeout(myfunction, 150); //'adjust for the amount of time you wish to yield (depends how much screen drawing is required or etc)
  }
}
var myfuncGen = myfuncSurrogate(); //'creates a "Generator" out of next. 
function* myfuncSurrogate() { //'This the original function repackaged! Note asterisk. 
//'-------------------------------------End Insert    
  var ms;       //...your original function continues here....
  for (var i = 1; i <= 9; i++) { //'sample 9x loop
    ms = new Date().getTime();
    while (new Date().getTime() < ms + 500); //'PAUSE (get time & wait 500ms) as an example of being busy
    misc++; //'example manipulating an external var
    outputdiv.innerHTML = "Output Div<br>demonstrating progress.. " + misc;
    yield; //'replacement for your doevents, all internal stack state and variables effectively hibernate.
  }
  console.log("done");
}

myfunction(); //'and start by calling here. Note that you can use "return" to return a value except by call backs.
&#13;
<div id='outputdiv' align='center'></div>
&#13;
&#13;
&#13;

..如果您对这一切都不熟悉,请注意,如果没有插入和yield关键字,您只需等待5秒而没有任何事情发生,然后进度{div}将会读取&#34; 9&#34; (因为{div}的所有其他更改都是不可见的)。