क्या 'तो' वास्तव में CasperJS में मतलब है


97

मैं एक वेबसाइट के माध्यम से क्लिक, पूर्ण किए गए फ़ॉर्म, पार्सिंग डेटा आदि की एक श्रृंखला को स्वचालित करने के लिए CasperJS का उपयोग कर रहा हूं।

कैस्पर को 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कथन से पहले चलता है और मुझे नहीं पता कि क्यों।


1
मैं अभी भी flowकेसपरज के जनरल के स्पष्टीकरण की तलाश में हूं, लेकिन मैंने पाया है कि आप मूल रूप से evaluateकॉल करने के लिए कैस्पर को संदर्भित नहीं कर सकते । (यानी आप एक नया यूआरएल, लॉग, इको आदि नहीं खोल सकते हैं)। इसलिए मेरे मामले में मूल्यांकन को बुलाया जा रहा था लेकिन बाहरी दुनिया के साथ बातचीत करने का कोई तरीका नहीं था।
बेंडाईट्री

1
मैं बिल्कुल वही बातें सोच रहा था, लेकिन पूछने के लिए बहुत आलसी था। अच्छा प्रश्न!
नाथन

4
evaluate()उस कोड के लिए है जो "ब्राउज़र" में चलता है, पेज के डोम में pomomjs ब्राउज़ कर रहा है। तो वहाँ कोई नहीं casper.openहै, लेकिन वहाँ jQuery हो सकता है। तो आपके उदाहरण का कोई मतलब नहीं है, लेकिन मुझे अभी भी आश्चर्य है कि then()वास्तव में क्या करता है।
नाथन

जवाबों:


93

then()मूल रूप से एक स्टैक में एक नया नेविगेशन कदम जोड़ता है। एक चरण एक जावास्क्रिप्ट फ़ंक्शन है जो दो अलग-अलग चीजें कर सकता है:

  1. पिछले चरण की प्रतीक्षा कर रहा है - यदि कोई हो - निष्पादित किया जा रहा है
  2. लोड करने के लिए अनुरोधित 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()समारोह जो हमारे लिए यूआरएल को लोड करने CasperJS द्वारा स्वचालित रूप से जोड़ दिया गया है; जब url लोड किया जाता है, तो स्टैक में उपलब्ध अगला चरण - जो है step3()- कहा जाता है।

जब आपने अपने नेविगेशन चरणों को परिभाषित कर लिया है, तो run()उन्हें एक-एक करके क्रमिक रूप से निष्पादित करें:

casper.run();

फुटनोट: कॉलबैक / श्रोता सामग्री वादा पैटर्न का कार्यान्वयन है ।


कास्परजेस 1.0.0-RC1 में, "टेस्ट-स्टेप्स.जेएस" फंक्शन डेफिनिशन स्ट्रिंग्स के संग्रह के बजाय, [ऑब्जेक्ट DOMWindow] का एक संग्रह प्रदर्शित कर रहा है।
स्टार्कलॉक

[ऑब्जेक्ट DOMWindow] संग्रह अभी भी 1.0.0-RC4 में परिणाम है; मुझे आश्चर्य है कि उन कार्य परिभाषाएँ कहाँ चली गईं ...
स्टार

1
मैंने शुरू में सोचा था कि CasperJS DOMWindows में फ़ंक्शंस को परिवर्तित करने का एक नया ट्रिक कर रहा था, लेकिन समस्या वास्तव में "return this.toString ()" बनाम "return step.toString ()" थी - मैंने उत्तर के लिए एक एडिट सबमिट किया।
स्टार्कलॉक

5
तथाकथित 'स्टैक' वास्तव में एक कतार नहीं है? कदम क्रम में निष्पादित किए जाते हैं, क्या यह एक स्टैक था जो हम चरण 3, चरण 2, चरण 1 की अपेक्षा नहीं करेंगे?
रीट शरबानी

1
मुझे लगता है कि यह इस तरह होना चाहिए: आपके पास चरणों का ढेर है। आप एक स्टेप को बंद करके उसका मूल्यांकन करते हैं। आप एक खाली कतार बनाएँ। वर्तमान चरण के प्रसंस्करण के कारण उत्पन्न कोई भी कदम इस कतार में डाल दिया जाता है। जब चरण का मूल्यांकन समाप्त हो जाता है, तो कतार में सभी उत्पन्न चरण ढेर के ऊपर डाल दिए जाते हैं, लेकिन उनकी कतार के भीतर उनके क्रम को संरक्षित करते हैं। (रिवर्स ऑर्डर में स्टैक पर पुश करने के समान)।
मार्क

33

then() केवल चरणों की एक श्रृंखला पंजीकृत करता है।

run() और धावक कार्यों, कॉलबैक और श्रोताओं के अपने परिवार, वास्तव में प्रत्येक चरण को निष्पादित करने का काम करते हैं।

जब भी कोई कदम पूरा हो गया है, CasperJS 3 झंडे के खिलाफ जाँच करेगा: pendingWait, loadInProgress, और navigationRequested। यदि उनमें से कोई भी ध्वज सत्य है, तो कुछ भी न करें, बाद के समय ( setIntervalशैली) तक निष्क्रिय रहें । यदि उन झंडे में से कोई भी सच नहीं है, तो अगले चरण को निष्पादित किया जाएगा।

CasperJS 1.0.0-RC4 के रूप में, एक दोष मौजूद है, जहां, कुछ समय-आधारित परिस्थितियों में, "अगला चरण करने का प्रयास करें" विधि शुरू हो जाएगी, इससे पहले कि CasperJS में से किसी एक loadInProgressया navigationRequestedझंडे को उठाने का समय हो । समाधान यह है कि किसी भी कदम को छोड़ने से पहले उन झंडों को उठाया जाए, जहां उन झंडों को उठाए जाने की उम्मीद है (उदाहरण के लिए: इससे पहले या बाद में एक झंडा उठाएं casper.click()), शायद ऐसा हो:

(नोट: यह केवल उदाहरण है, उचित कैस्परजेएस फॉर्म की तुलना में प्यूसेकोड से अधिक ...)

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()
}

उस समाधान को कोड की एकल-पंक्ति में लपेटने के लिए, मैंने blockStep()इस गीथब पुल अनुरोध में पेश किया , जिसका विस्तार click()और clickLabel()गारंटी के रूप में यह सुनिश्चित करने में मदद करता है कि हम उपयोग करते समय अपेक्षित व्यवहार प्राप्त करें then()। अधिक जानकारी, उपयोग पैटर्न और न्यूनतम परीक्षण फ़ाइलों के लिए अनुरोध देखें।


1
बहुत उपयोगी और महान अंतर्दृष्टि और सुझाव पर blockStep, IMHO
ब्रायन एम। हंट

हम अभी भी "अंतिम उत्तर" समाधान पर चर्चा कर रहे हैं ... मुझे उम्मीद है कि एक बार "वैश्विक चूक" पहलू को लागू करने के बाद, कैस्परजेएस पुल बना देगा।
स्टार

1
तो हाँ, इस पर नज़र रखें। :)
Starlocke

क्या हमारे पास इसका कोई हल है? यदि हां, तो यह क्या है ?
सुरेंद्र सिंह मलिक

यह समझाने के लिए बहुत बहुत धन्यवाद। यह व्यवहार मुझे एक साल से अधिक समय से मार रहा है क्योंकि अजाक्स-भारी एप्लिकेशन के लिए मेरे कैस्पर कार्यात्मक परीक्षण हर समय बेतरतीब ढंग से विफल होते हैं।
brettjonesdev

0

CasperJS प्रलेखन के अनुसार :

then()

हस्ताक्षर: then(Function then)

यह विधि एक सरल कार्य प्रदान करके, स्टैक में एक नया नेविगेशन चरण जोड़ने का मानक तरीका है:

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();

आप जितने आवश्यक हो उतने चरण जोड़ सकते हैं। ध्यान दें कि वर्तमान Casperउदाहरण स्वचालित रूप से thisआपके लिए चरण फ़ंक्शंस में कीवर्ड को बांधता है ।

आपके द्वारा परिभाषित सभी चरणों को चलाने के लिए, run()विधि और वॉइला को कॉल करें ।

नोट: विधि start()का उपयोग करने के लिए आपको कैस्पर उदाहरण होना चाहिए then()

चेतावनी: चरणबद्ध कार्य then()दो अलग-अलग मामलों में संसाधित किए जाते हैं:

  1. जब पिछले चरण फ़ंक्शन निष्पादित किया गया है,
  2. जब पिछला मुख्य HTTP अनुरोध निष्पादित हो गया हो और पेज लोड हो गया हो ;

ध्यान दें कि पेज लोड की कोई एक परिभाषा नहीं है ; क्या यह तब है जब DOMReady घटना को ट्रिगर किया गया है? क्या यह "सभी अनुरोध समाप्त हो रहे हैं"? क्या यह "सभी एप्लिकेशन लॉजिक प्रदर्शन किया जा रहा है"? या "सभी तत्वों का प्रतिपादन किया जा रहा है"? उत्तर हमेशा संदर्भ पर निर्भर करता है। इसलिए आपको हमेशा इसका उपयोग करने के लिए प्रोत्साहित क्यों किया जाता हैwaitFor() परिवार के तरीकों का जाता है ताकि आप वास्तव में जो उम्मीद करते हैं उस पर स्पष्ट नियंत्रण रखें।

एक सामान्य चाल है waitForSelector():

casper.start('http://my.website.com/');

casper.waitForSelector('#plop', function() {
  this.echo('I\'m sure #plop is available in the DOM');
});

casper.run();

पर्दे के पीछे, स्रोत कोडCasper.prototype.then नीचे दिखाया गया है:

/**
 * 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;
};

स्पष्टीकरण:

दूसरे शब्दों में, then() में, नेविगेशन प्रक्रिया में अगला चरण निर्धारित करता है।

कब then() कहा जाता है, तो इसे एक फ़ंक्शन के रूप में एक पैरामीटर पास किया जाता है जिसे एक चरण के रूप में कहा जाता है।

यह जाँचता है कि क्या कोई उदाहरण शुरू हो गया है, और यदि ऐसा नहीं है, तो यह निम्न त्रुटि प्रदर्शित करता है:

CasperError: Casper is not started, can't execute `then()`.

अगला, यह जाँचता है कि क्या pageवस्तु है null

यदि स्थिति सही है, तो कैस्पर एक नई pageवस्तु बनाता है ।

उसके बाद, यदि यह फ़ंक्शन नहीं है, तो जांच then()करने के लिए stepपैरामीटर को मान्य करता है।

यदि पैरामीटर एक फ़ंक्शन नहीं है, तो यह निम्न त्रुटि प्रदर्शित करता है:

CasperError: You can only define a step as a function

फिर, फ़ंक्शन जाँचता है कि कैस्पर चल रहा है या नहीं।

यदि कैस्पर नहीं चल रहा है, then()तो कतार के अंत में कदम जोड़ता है।

अन्यथा, यदि कैस्पर चल रहा है, तो यह पिछले चरण की तुलना में एक स्तर गहरा एक सबस्टेप सम्मिलित करता है।

अंत में, then()समारोह एक step.addedघटना का उत्सर्जन करके समाप्त होता है , और कैस्पर ऑब्जेक्ट को वापस करता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.