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

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

如果您的应用程序确实需要长时间运行的JavaScript代码,那么处理它的最佳方法之一就是使用JavaScript Web worker 。 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); } 

通过在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转换程序运行它,以便在常见浏览器上运行。

您可以使用setTimeout:

 setTimeout(function() { }, 3600); 

3600是时间,以毫秒为单位:

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

没有与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应用程序中几乎不需要。 可能会有一个你可以使用的事件,你错过了。 你真正的问题是什么?

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

(我使用过Web Worker,它很棒,但它远离DoEvents,几乎不可能访问全局变量)。 这已经过格式化以便于理解,并试图显示所需的额外内容(使函数处理产量)可以被视为原始函数中的插入。 “yield”具有各种其他function,但因此使用它,它几乎是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
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.