CasperJS에서 'Then'은 실제로 무엇을 의미합니까?
CasperJS를 사용하여 웹 사이트를 통해 일련의 클릭, 완성 된 양식, 데이터 구문 분석 등을 자동화하고 있습니다.
Casper는 then
명령문 형식의 사전 설정 단계 목록으로 구성되어있는 것 같습니다 (예 : http://casperjs.org/quickstart.html ).하지만 다음 명령문이 실제로 실행되도록 트리거하는 것은 명확하지 않습니다.
예를 들어 then
보류중인 모든 요청이 완료 될 때까지 기다리나요? injectJS
보류중인 요청으로 간주 됩니까 ? then
문이 중첩 된 경우-문 끝에 연결 되면 어떻게됩니까 open
?
casper.thenOpen('http://example.com/list', function(){
casper.page.injectJs('/libs/jquery.js');
casper.evaluate(function(){
var id = jQuery("span:contains('"+itemName+"')").closest("tr").find("input:first").val();
casper.open("http://example.com/show/"+id); //what if 'then' was added here?
});
});
casper.then(function(){
//parse the 'show' page
});
CasperJS에서 흐름이 어떻게 작동하는지에 대한 기술적 설명을 찾고 있습니다. 내 특정 문제는 내 마지막 then
진술 (위)이 내 casper.open
진술 보다 먼저 실행되고 이유를 모르겠다는 것입니다.
then()
기본적으로 스택에 새로운 탐색 단계를 추가합니다. 단계는 두 가지 다른 작업을 수행 할 수있는 자바 스크립트 함수입니다.
- 이전 단계 대기 (있는 경우) 실행 중
- 요청 된 URL 및 관련 페이지가로드되기를 기다리는 중
간단한 탐색 시나리오를 살펴 보겠습니다.
var casper = require('casper').create();
casper.start();
casper.then(function step1() {
this.echo('this is step one');
});
casper.then(function step2() {
this.echo('this is step two');
});
casper.thenOpen('http://google.com/', function step3() {
this.echo('this is step 3 (google.com is loaded)');
});
다음과 같이 스택 내에서 생성 된 모든 단계를 인쇄 할 수 있습니다.
require('utils').dump(casper.steps.map(function(step) {
return step.toString();
}));
그 결과 :
$ casperjs test-steps.js
[
"function step1() { this.echo('this is step one'); }",
"function step2() { this.echo('this is step two'); }",
"function _step() { this.open(location, settings); }",
"function step3() { this.echo('this is step 3 (google.com is loaded)'); }"
]
_step()
우리를 위해 URL을로드하기 위해 CasperJS에 의해 자동으로 추가 된 함수에 주목 하십시오. URL이로드되면 스택에서 사용할 수있는 다음 단계 (즉) step3()
가 호출됩니다.
When you have defined your navigation steps, run()
executes them one by one sequentially:
casper.run();
Footnote: the callback/listener stuff is an implementation of the Promise pattern.
then()
merely registers a series of steps.
run()
and its family of runner functions, callbacks, and listeners, are all what actually do the work of executing each step.
Whenever a step is completed, CasperJS will check against 3 flags: pendingWait
, loadInProgress
, and navigationRequested
. If any of those flags is true, then do nothing, go idle until a later time (setInterval
style). If none of those flags is true, then the next step will get executed.
As of CasperJS 1.0.0-RC4, a flaw exists, where, under certain time-based circumstances, the "try to do next step" method will be triggered before CasperJS had the time to raise either one of the loadInProgress
or navigationRequested
flags. The solution is to raise one of those flags before leaving any step where those flags are expected to be raised (ex: raise a flag either before or after asking for a casper.click()
), maybe like so:
(Note: This is only illustrative, more like psuedocode than proper CasperJS form...)
step_one = function(){
casper.click(/* something */);
do_whatever_you_want()
casper.click(/* something else */); // Click something else, why not?
more_magic_that_you_like()
here_be_dragons()
// Raise a flag before exiting this "step"
profit()
}
To wrap up that solution into a single-line of code, I introduced blockStep()
in this github pull request, extending click()
and clickLabel()
as a means to help guarantee that we get the expected behaviour when using then()
. Check out the request for more info, usage patterns, and minimum test files.
According to the CasperJS Documentation:
then()
Signature: then(Function then)
This method is the standard way to add a new navigation step to the stack, by providing a simple function:
casper.start('http://google.fr/');
casper.then(function() {
this.echo('I\'m in your google.');
});
casper.then(function() {
this.echo('Now, let me write something');
});
casper.then(function() {
this.echo('Oh well.');
});
casper.run();
You can add as many steps as you need. Note that the current
Casper
instance automatically binds thethis
keyword for you within step functions.To run all the steps you defined, call the
run()
method, and voila.Note: You must
start()
the casper instance in order to use thethen()
method.Warning: Step functions added to
then()
are processed in two different cases:
- when the previous step function has been executed,
- when the previous main HTTP request has been executed and the page loaded;
Note that there's no single definition of page loaded; is it when the DOMReady event has been triggered? Is it "all requests being finished"? Is it "all application logic being performed"? Or "all elements being rendered"? The answer always depends on the context. Hence why you're encouraged to always use the
waitFor()
family methods to keep explicit control on what you actually expect.A common trick is to use
waitForSelector()
:
casper.start('http://my.website.com/');
casper.waitForSelector('#plop', function() {
this.echo('I\'m sure #plop is available in the DOM');
});
casper.run();
Behind the scenes, the source code for Casper.prototype.then
is shown below:
/**
* Schedules the next step in the navigation process.
*
* @param function step A function to be called as a step
* @return Casper
*/
Casper.prototype.then = function then(step) {
"use strict";
this.checkStarted();
if (!utils.isFunction(step)) {
throw new CasperError("You can only define a step as a function");
}
// check if casper is running
if (this.checker === null) {
// append step to the end of the queue
step.level = 0;
this.steps.push(step);
} else {
// insert substep a level deeper
try {
step.level = this.steps[this.step - 1].level + 1;
} catch (e) {
step.level = 0;
}
var insertIndex = this.step;
while (this.steps[insertIndex] && step.level === this.steps[insertIndex].level) {
insertIndex++;
}
this.steps.splice(insertIndex, 0, step);
}
this.emit('step.added', step);
return this;
};
Explanation:
In other words, then()
schedules the next step in the navigation process.
When then()
is called, it is passed a function as a parameter which is to be called as a step.
It checks if an instance has started, and if it has not, it displays the following error:
CasperError: Casper is not started, can't execute `then()`.
Next, it checks if the page
object is null
.
If the condition is true, Casper creates a new page
object.
After that, then()
validates the step
parameter to check if it is not a function.
If the parameter is not a function, it displays the following error:
CasperError: You can only define a step as a function
Then, the function checks if Casper is running.
If Casper is not running, then()
appends the step to the end of the queue.
Otherwise, if Casper is running, it inserts a substep a level deeper than the previous step.
Finally, the then()
function concludes by emitting a step.added
event, and returns the Casper object.
참고URL : https://stackoverflow.com/questions/11604611/what-does-then-really-mean-in-casperjs
'programing tip' 카테고리의 다른 글
배치 파일을 사용하여 현재 작업 디렉토리를 변경하는 방법 (0) | 2020.08.25 |
---|---|
SQL Developer에서 변수 값 인쇄 (0) | 2020.08.25 |
std :: queue :: pop이 값을 반환하지 않는 이유는 무엇입니까? (0) | 2020.08.24 |
node.js의 ES6 변수 가져 오기 이름? (0) | 2020.08.24 |
"2016-02-16"이 "2016-02-16 00:00"과 같지 않은 이유는 무엇입니까? (0) | 2020.08.24 |