如何在JavaScript中强制执行单线程行为
How can I force single threaded behavior in JavaScript?
我是JavaScript的新手,我只是在学习如何使用它的并发模型。现在,我有以下代码,我正试图在其中实现busyWait函数:
function captureFile() {
return "screenshots/anthem" + ++numCaptures + ".png"
};
function busyWait(casper, selector, action) {
casper.echo('busyWait', 'INFO');
casper.waitUntilVisible(
selector,
function then() {
this.capture(captureFile());
casper.captureSelector(captureFile(), selector);
casper.echo(selector + ' is Visible', 'INFO');
action(casper);
},
function onTimeout() {
casper.capture(captureFile());
casper.echo('Continue to Wait', 'INFO');
busyWait(casper, selector);
},
1000
);
};
casper.start(anthem_url, function () {
// Try to find the survey and dismiss it.
var surveyID = 'div.fsrFloatingContainer';
busyWait(this, surveyID, function action(casper) {
casper.clickLabel('No, thanks', 'a');
casper.echo('Dismissed Survey', 'INFO');
});
// enter Last Name
var nameID = '#ctl00_MainContent_maincontent_SearchWizard6_LastName';
busyWait(this, nameID, function action(casper) {
casper.sendKeys(nameID, name);
casper.echo('Set Name to: ' + name, 'INFO');
});
this.sendKeys(nameID, name);
this.capture(captureFile());
});
casper.run(function () {
this.exit();
});
运行上面的代码返回:
$casperjs casper_anthem.js
busyWait
busyWait
div.fsrFloatingContainer is Visible
Dismissed Survey
#ctl00_MainContent_maincontent_SearchWizard6_LastName is Visible
Set Name to: Smith
所以,问题是我使用回调来实现busyWait循环。当然,这不起作用,因为回调在JavaScript中是异步的。我的问题是:如何从回调中强制执行同步行为?
解决方案
事实证明,CasperJS中的then()
函数实际上就是实现这一点的方法。
function busyWait(casper, selector, action) {
casper.waitUntilVisible(
selector,
function then() {
casper.echo(selector + ' is Visible', 'INFO');
casper.captureSelector(captureFile(), selector);
action(casper);
casper.capture(captureFile());
},
function onTimeout() {
casper.echo('Continue to Wait for ' + selector, 'INFO');
casper.capture(captureFile());
busyWait(casper, selector, function action(casper) { action(casper) });
},
5000
);
};
casper.start(anthem_url);
// Try to find the survey and dismiss it.
casper.then(function () {
this.capture(captureFile());
busyWait(this, surveyID, function action(casper) {
casper.clickLabel('No, thanks', 'a');
casper.echo('Dismissed Survey', 'INFO');
});
});
// enter Last Name
casper.then(function () {
var nameID = '#ctl00_MainContent_maincontent_SearchWizard6_LastName';
this.waitWhileSelector(surveyID, function () {
busyWait(this, nameID, function action(casper) {
casper.sendKeys(nameID, name);
casper.echo('Set Name to: ' + name, 'INFO');
});
});
});
casper.run();
基本上,我只需要将每个操作放在它自己的then()
块中,并让CasperJS管理序列化它们。
then
函数中进行编码,该函数将在主代码块完成后执行。如果您要向用户提供一系列输入,并且每个输入(如文本或按钮)的性质取决于以前输入的结果,那么您最终会得到很多嵌套的回调。(这就是它应该如何工作。)
(在实践中,你可以通过调用函数来完成这项工作,使其看起来更好。这节省了缩进,但这意味着查看代码的人需要一段时间才能弄清楚代码的真实流程。)
在你习惯之前,倾向于编写顺序代码:
first do this ...
then do this ...
then this ...
而这在这种UI中是不起作用的。
相关文章:
- 事件循环、回调队列和 Javascript 的单线程是如何连接的
- 使用技巧在javascript中强制执行私有继承
- Javascript RegEx-强制执行两个最大长度
- 在 gruntjs 构建失败的情况下强制执行某些任务
- 浏览器仍然是单线程的吗
- 在ExtJs 4网格中强制执行唯一键值
- 当javascript是单线程时,谁是onreadystatechange的调用者
- 强制执行本地托管Web应用程序的许可证
- 如何在JavaScript中强制执行单线程行为
- 对文本框强制执行大小写约束
- 用于强制执行 JSON 结构的 Javascript 类
- 节点JS单线程与多线程(CPU利用率:有什么区别吗?
- JSHINT:有没有办法忽略仅驼峰大小写属性并将其强制执行到变量和函数上
- 单线程 Javascript 和 AJAX 处理
- 如何使用 JavaScript 在输入后强制执行函数
- 唯一字段约束在 dropDatabase 之后未强制执行
- JavaScript 回调在主线程中执行
- 单线程 JavaScript 下的动画
- 有没有办法检查是否强制执行严格模式
- 如果JavaScript(大部分)是同步的和单线程的,为什么while循环没有阻止进一步语句的执行