javascript - प्रबंधित बीन से एक जावास्क्रिप्ट फ़ंक्शन को कॉल करना




jsf primefaces managed-bean (5)

प्राइमफेसेस प्री 6.2 में, आप इसके लिए RequestContext#execute() उपयोग कर सकते हैं।

public void submit() {
    // ...
    RequestContext.getCurrentInstance().execute("alert('peek-a-boo');");
}

प्राइमफेस 6.2 और ऊपर में:

public void submit() {
    // ...
    PrimeFaces.current().executeScript("alert('peek-a-boo');");
}

मानक जेएसएफ में, इसके लिए कोई प्रत्यक्ष सार्वजनिक एपीआई नहीं है। वांछित स्क्रिप्ट को एक बीन संपत्ति के रूप में सेट करना और सशर्त रूप से <h:outputScript> घटक प्रस्तुत करना है जब बीन संपत्ति खाली नहीं है।

<h:commandButton ... action="#{bean.submit}" />
<h:outputScript rendered="#{not empty bean.script}">#{bean.script}</h:outputScript>
public void submit() {
    // ...
    script = "alert('peek-a-boo');";
}

यदि आप AJAX द्वारा फ़ॉर्म सबमिट कर रहे हैं, तो <h:outputScript> को किसी अन्य घटक में लपेटना न भूलें और इसके बजाय <h:outputScript> अपडेट करें। यह भी देखें कि अजाक्स अपडेट / रेंडर एक घटक पर काम नहीं करता है जिसने विशेषता प्रदान की है

<h:commandButton ... action="#{bean.submit}">
    <f:ajax execute="@form" render="script" />
</h:commandButton>
<h:panelGroup id="script">
    <h:outputScript rendered="#{not empty bean.script}">#{bean.script}</h:outputScript>
</h:panelGroup>

"उस के लिए कोई प्रत्यक्ष सार्वजनिक एपीआई नहीं है" कथन, उत्सुकता से PartialResponseWriter क्लास (जेएसएफ AJAX प्रतिक्रिया लिखने के लिए ज़िम्मेदार) पहले से ही जेएसएफ 2.0 startEval() और endEval() विधियों से है जो आपको सीधे कॉलबैक स्क्रिप्ट लिखने में सक्षम बनाता है प्रतिक्रिया लेकिन आगामी जेएसएफ 2.3 तक आश्चर्यजनक रूप से PartialViewContext में कोई सार्वजनिक विधि नहीं है जो उन तरीकों से प्रतिनिधि होगी। मुद्दे के अनुसार 1412 PartialViewContext#getEvalScripts() को अंततः सार्वजनिक एपीआई में जोड़ा गया है।

public void submit() {
    // ...
    FacesContext.getCurrentInstance().getPartialViewContext().getEvalScripts().add("alert('peek-a-boo');");
}

पुराने जेएसएफ संस्करणों के लिए, इसे केवल कस्टम PartialViewContext कार्यान्वयन बनाकर कार्यान्वित किया जा सकता है। जेएसएफ यूटिलिटी लाइब्रेरी ओमनीफेस ने ओमनीपार्टियल व्यू कॉन्टेक्स्ट के साथ बिल्कुल किया है जिसका प्रयोग Ajax यूटिलिटी क्लास के माध्यम से किया जा सकता है।

public void submit() {
    // ...
    Ajax.oncomplete("alert('peek-a-boo');");
}

यह भी देखें:

जेएसएफ में प्रबंधित बीन से जावास्क्रिप्ट फ़ंक्शन को कॉल करने (निष्पादित करने का कोई तरीका है?

यदि यह प्रासंगिक है, तो मैं प्राइमफेस का भी उपयोग कर रहा हूं।


आम तौर पर, जावा एक स्क्रिप्टिंग इंजन का उपयोग कर स्ट्रिंग का मूल्यांकन करने के लिए एक एपीआई प्रदान करता है। यह javax.script.ScriptEngine और javax.script.ScriptEngineManager कक्षाओं द्वारा पूरा किया जा सकता है।

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

अधिक जानकारी के लिए, इस लिंक को देखें: http://docs.oracle.com/javase/6/docs/technotes/guides/scripting/programmer_guide/index.html


आप जिस प्राइमफेस पर हैं, उसके आधार पर आप RequestContext.execute("{js here}"); उपयोग कर सकते हैं RequestContext.execute("{js here}");

प्राइमफेस से 3.4 दस्तावेज:

जब अनुरोध AJAX अनुरोध पूरा हो जाता है, तो अनुरोध कॉन्टेक्स्ट जावास्क्रिप्ट निष्पादित करने का एक तरीका प्रदान करता है, यह दृष्टिकोण गुजरने वाले कॉलबैक पैराम की तुलना में आसान है और सशर्त जावास्क्रिप्ट निष्पादित करता है। AJAX अनुरोध पूरा होने पर नीचे दिया गया उदाहरण संवाद को छुपाता है;

कोड

public void save() {
  RequestContext requestContext = RequestContext.getCurrentInstance();  
  requestContext.execute("dialog.hide()");
}


→ विभिन्न उदाहरणों के साथ एसिंक व्यवहार के बारे में अधिक सामान्य स्पष्टीकरण के लिए, कृपया एक फ़ंक्शन के अंदर इसे संशोधित करने के बाद मेरा चर अपरिवर्तित क्यों है? असीमित कोड संदर्भ

→ यदि आप पहले से ही समस्या को समझते हैं, तो नीचे दिए गए संभावित समाधानों पर जाएं।

समस्या

Ajax में asynchronous के लिए खड़ा है। इसका मतलब है कि अनुरोध भेजना (या प्रतिक्रिया प्राप्त करना) सामान्य निष्पादन प्रवाह से बाहर निकाला जाता है। आपके उदाहरण में, $.ajax तुरंत और अगला कथन लौटाता है, return result; , success कॉलबैक के रूप में पारित समारोह से पहले निष्पादित किया जाता है।

यहां एक समानता है जो उम्मीद है कि तुल्यकालिक और असिंक्रोनस प्रवाह स्पष्ट के बीच का अंतर बनाता है:

एक समय का

कल्पना कीजिए कि आप किसी मित्र को फोन करें और उसे आपके लिए कुछ देखने के लिए कहें। यद्यपि इसमें कुछ समय लग सकता है, आप फोन पर इंतजार करते हैं और अंतरिक्ष में घूमते हैं, जब तक कि आपका मित्र आपको आवश्यक उत्तर न दे।

वही हो रहा है जब आप "सामान्य" कोड वाले फ़ंक्शन कॉल करते हैं:

function findItem() {
    var item;
    while(item_not_found) {
        // search
    }
    return item;
}

var item = findItem();

// Do something with item
doSomethingElse();

भले ही findItem निष्पादित करने में लंबा समय लगे, फिर भी कोई var item = findItem(); बाद आ रहा है var item = findItem(); फ़ंक्शन परिणाम लौटने तक प्रतीक्षा करना होगा

अतुल्यकालिक

आप उसी कारण से अपने दोस्त को फिर से बुलाते हैं। लेकिन इस बार आप उसे बताते हैं कि आप जल्दबाजी में हैं और उन्हें आपको अपने मोबाइल फोन पर वापस कॉल करना चाहिए। आप लटकाते हैं, घर छोड़ते हैं और जो कुछ भी करने की योजना बनाते हैं उसे करें। एक बार जब आपका मित्र आपको वापस बुलाता है, तो आप उस जानकारी से निपट रहे हैं जो उसने आपको दिया था।

जब आप अजाक्स अनुरोध करते हैं तो वही हो रहा है।

findItem(function(item) {
    // Do something with item
});
doSomethingElse();

प्रतिक्रिया की प्रतीक्षा करने के बजाय, निष्पादन तुरंत जारी रहता है और अजाक्स कॉल के बाद बयान निष्पादित किया जाता है। अंततः प्रतिक्रिया प्राप्त करने के लिए, प्रतिक्रिया मिलने के बाद आप एक समारोह कहलाते हैं, कॉलबैक (कुछ नोटिस? वापस कॉल करें ?)। कॉलबैक कहने से पहले उस कॉल के बाद आने वाला कोई भी बयान निष्पादित किया जाता है।

समाधान की)

जावास्क्रिप्ट की असीमित प्रकृति को गले लगाओ! जबकि कुछ एसिंक्रोनस ऑपरेशंस सिंक्रोनस समकक्ष प्रदान करते हैं (इसलिए "अजाक्स" भी), आमतौर पर उन्हें उपयोग करने के लिए निराश किया जाता है, खासकर ब्राउज़र संदर्भ में।

आप पूछना बुरा क्यों है?

जावास्क्रिप्ट ब्राउज़र के यूआई थ्रेड में चलता है और किसी भी लंबी चलती प्रक्रिया यूआई को लॉक कर देगी, जिससे इसे उत्तरदायी बना दिया जाएगा। इसके अतिरिक्त, जावास्क्रिप्ट के लिए निष्पादन समय पर ऊपरी सीमा है और ब्राउज़र उपयोगकर्ता से पूछेगा कि निष्पादन जारी रखना है या नहीं।

यह सब वास्तव में खराब उपयोगकर्ता अनुभव है। उपयोगकर्ता यह बताने में सक्षम नहीं होगा कि सब ठीक काम कर रहा है या नहीं। इसके अलावा, धीमे कनेक्शन वाले उपयोगकर्ताओं के लिए प्रभाव खराब होगा।

निम्नलिखित में हम तीन अलग-अलग समाधान देखेंगे जो सभी एक दूसरे के शीर्ष पर हैं:

  • async/await await के साथ वादे (ES2017 +, पुराने ब्राउज़र में उपलब्ध है यदि आप एक ट्रांसलेटर या पुनर्विक्रेता का उपयोग करते हैं)
  • कॉलबैक (नोड में लोकप्रिय)
  • then() साथ वादे then() (ES2015 +, पुराने ब्राउज़र में उपलब्ध है यदि आप कई वादे पुस्तकालयों में से एक का उपयोग करते हैं)

सभी तीन वर्तमान ब्राउज़र में उपलब्ध हैं, और नोड 7+।

ES2017 +: async/await साथ वादा async/await

2017 में जारी ईसीएमएस्क्रिप्ट संस्करण ने एसिंक्रोनस फ़ंक्शंस के लिए सिंटैक्स-स्तरीय समर्थन प्रस्तुत किया। async और await की मदद से, आप "तुल्यकालिक शैली" में एसिंक्रोनस लिख सकते हैं। कोड अभी भी असंकालिक है, लेकिन इसे पढ़ने / समझना आसान है।

async/await वादे के शीर्ष पर बनाता है: एक async समारोह हमेशा एक वादा देता है। एक वादा "अनचाहे" का await और या तो वादा को अस्वीकार कर दिया गया था या तो वादा को अस्वीकार कर दिया गया था या तो वादा को खारिज कर दिया गया था।

महत्वपूर्ण: आप केवल async फ़ंक्शन के अंदर await उपयोग कर सकते हैं। इसका मतलब है कि बहुत ऊपर के स्तर पर, आपको अभी भी वादे के साथ सीधे काम करना है।

आप async/await बारे में अधिक पढ़ सकते हैं और एमडीएन पर await कर सकते हैं।

यहां एक उदाहरण दिया गया है जो उपरोक्त देरी के शीर्ष पर बनाता है:

// Using 'superagent' which will return a promise.
var superagent = require('superagent')

// This is isn't declared as `async` because it already returns a promise
function delay() {
  // `delay` returns a promise
  return new Promise(function(resolve, reject) {
    // Only `delay` is able to resolve or reject the promise
    setTimeout(function() {
      resolve(42); // After 3 seconds, resolve the promise with value 42
    }, 3000);
  });
}


async function getAllBooks() {
  try {
    // GET a list of book IDs of the current user
    var bookIDs = await superagent.get('/user/books');
    // wait for 3 seconds (just for the sake of this example)
    await delay();
    // GET information about each book
    return await superagent.get('/books/ids='+JSON.stringify(bookIDs));
  } catch(error) {
    // If any of the awaited promises was rejected, this catch block
    // would catch the rejection reason
    return null;
  }
}

// Async functions always return a promise
getAllBooks()
  .then(function(books) {
    console.log(books);
  });

वर्तमान browser और node संस्करण async/await समर्थन करते हैं। आप regenerator (या उपकरण जो पुनर्विक्रेता का उपयोग करते हैं, जैसे Babel ) की मदद से ईएस 5 में अपना कोड बदलकर पुराने वातावरण का समर्थन कर सकते हैं।

कार्यों को कॉलबैक स्वीकार करने दें

एक कॉलबैक बस एक समारोह को दूसरे समारोह में पारित किया जाता है। वह अन्य फ़ंक्शन जब भी तैयार हो जाता है तो फ़ंक्शन को कॉल कर सकता है। एसिंक्रोनस प्रक्रिया के संदर्भ में, जब भी एसिंक्रोनस प्रक्रिया पूरी की जाती है तो कॉलबैक को कॉल किया जाएगा। आमतौर पर, परिणाम कॉलबैक को पास किया जाता है।

प्रश्न के उदाहरण में, आप foo को कॉलबैक स्वीकार कर सकते हैं और success कॉलबैक के रूप में इसका उपयोग कर सकते हैं। तो यह

var result = foo();
// Code that depends on 'result'

हो जाता है

foo(function(result) {
    // Code that depends on 'result'
});

यहां हमने फ़ंक्शन "इनलाइन" परिभाषित किया है लेकिन आप किसी फ़ंक्शन संदर्भ को पास कर सकते हैं:

function myCallback(result) {
    // Code that depends on 'result'
}

foo(myCallback);

foo खुद को निम्नानुसार परिभाषित किया गया है:

function foo(callback) {
    $.ajax({
        // ...
        success: callback
    });
}

callback उस फ़ंक्शन को संदर्भित करेगा जब हम इसे कॉल करते हैं, हम इसे कॉल करते हैं और हम इसे success पास करते हैं। एक बार अजाक्स अनुरोध सफल होने के बाद, $.ajax callback को कॉल करेगा और callback को प्रतिक्रिया देगी (जिसे result साथ संदर्भित किया जा सकता है, क्योंकि इस तरह हमने कॉलबैक को परिभाषित किया है)।

आप कॉलबैक में पास करने से पहले प्रतिक्रिया को भी संसाधित कर सकते हैं:

function foo(callback) {
    $.ajax({
        // ...
        success: function(response) {
            // For example, filter the response
            callback(filtered_response);
        }
    });
}

ऐसा लगता है कि कॉलबैक का उपयोग करके कोड लिखना आसान है। आखिरकार, ब्राउजर में जावास्क्रिप्ट भारी घटना-संचालित (डीओएम कार्यक्रम) है। अजाक्स प्रतिक्रिया प्राप्त करना एक घटना के अलावा कुछ और नहीं है।
कठिनाइयों का सामना तब हो सकता है जब आपको तीसरे पक्ष के कोड के साथ काम करना पड़ेगा, लेकिन अधिकांश समस्याओं को केवल आवेदन प्रवाह के माध्यम से हल करके हल किया जा सकता है।

ES2015 +: then() साथ वादे then()

then() एसीएमएस्क्रिप्ट 6 (ES2015) की एक नई सुविधा है, लेकिन इसमें पहले से ही अच्छा ब्राउज़र समर्थन है । ऐसे कई पुस्तकालय भी हैं जो मानक वादा एपीआई को लागू करते हैं और अतुल्यकालिक कार्यों (उदाहरण के लिए bluebird ) के उपयोग और संरचना को कम करने के लिए अतिरिक्त विधियां प्रदान करते हैं।

वादे भविष्य के मूल्यों के लिए कंटेनर हैं। जब वादा मूल्य प्राप्त करता है (इसे हल किया जाता है ) या जब इसे रद्द कर दिया जाता है ( अस्वीकार कर दिया जाता है ), यह अपने सभी "श्रोताओं" को सूचित करता है जो इस मूल्य तक पहुंचना चाहते हैं।

सादा कॉलबैक पर लाभ यह है कि वे आपको अपने कोड को कम करने की अनुमति देते हैं और उन्हें लिखना आसान होता है।

वादा का उपयोग करने का एक सरल उदाहरण यहां दिया गया है:

function delay() {
  // `delay` returns a promise
  return new Promise(function(resolve, reject) {
    // Only `delay` is able to resolve or reject the promise
    setTimeout(function() {
      resolve(42); // After 3 seconds, resolve the promise with value 42
    }, 3000);
  });
}

delay()
  .then(function(v) { // `delay` returns a promise
    console.log(v); // Log the value once it is resolved
  })
  .catch(function(v) {
    // Or do something else if it is rejected 
    // (it would not happen in this example, since `reject` is not called).
  });

हमारे अजाक्स कॉल पर लागू हम इस तरह के वादे का उपयोग कर सकते हैं:

function ajax(url) {
  return new Promise(function(resolve, reject) {
    var xhr = new XMLHttpRequest();
    xhr.onload = function() {
      resolve(this.responseText);
    };
    xhr.onerror = reject;
    xhr.open('GET', url);
    xhr.send();
  });
}

ajax("/echo/json")
  .then(function(result) {
    // Code depending on result
  })
  .catch(function() {
    // An error occurred
  });

प्रस्ताव का वादा करने वाले सभी फायदों का वर्णन इस उत्तर के दायरे से बाहर है, लेकिन यदि आप नया कोड लिखते हैं, तो आपको गंभीरता से उन पर विचार करना चाहिए। वे आपके कोड का एक महान अमूर्तता और अलगाव प्रदान करते हैं।

वादे के बारे में अधिक जानकारी: एचटीएमएल 5 चट्टानों - जावास्क्रिप्ट वादा करता है

साइड नोट: jQuery की स्थगित वस्तुओं

डिफर्ड ऑब्जेक्ट्स jQuery के वादे के कस्टम कार्यान्वयन हैं (वादा API को मानकीकृत करने से पहले)। वे लगभग वादे की तरह व्यवहार करते हैं लेकिन थोड़ा अलग एपीआई का पर्दाफाश करते हैं।

JQuery की प्रत्येक अजाक्स विधि पहले से ही "स्थगित वस्तु" (वास्तव में एक स्थगित वस्तु का वादा) लौटाती है जिसे आप अपने कार्य से वापस कर सकते हैं:

function ajax() {
    return $.ajax(...);
}

ajax().done(function(result) {
    // Code depending on result
}).fail(function() {
    // An error occurred
});

साइड नोट: वादा गेटचास

ध्यान रखें कि वादे और स्थगित वस्तुएं भविष्य के मूल्य के लिए केवल कंटेनर हैं, वे मूल्य स्वयं नहीं हैं। उदाहरण के लिए, मान लें कि आपके पास निम्न था:

function checkPassword() {
    return $.ajax({
        url: '/password',
        data: {
            username: $('#username').val(),
            password: $('#password').val()
        },
        type: 'POST',
        dataType: 'json'
    });
}

if (checkPassword()) {
    // Tell the user they're logged in
}

यह कोड उपरोक्त एसिंक्रोनि मुद्दों को गलत समझाता है। विशेष रूप से, $.ajax() कोड को फ्रीज नहीं करता है, जबकि यह आपके सर्वर पर 'पासवर्ड' पृष्ठ की जांच करता है - यह सर्वर से अनुरोध भेजता है और जब यह प्रतीक्षा करता है, तो तुरंत एक jQuery अजाक्स डिफरर्ड ऑब्जेक्ट देता है, प्रतिक्रिया नहीं सर्वर। इसका मतलब है कि if कथन हमेशा इस डिफर्ड ऑब्जेक्ट को प्राप्त करने जा रहा है, तो इसे true मानें, और आगे बढ़ें जैसे कि उपयोगकर्ता लॉग इन है। अच्छा नहीं।

लेकिन फिक्स आसान है:

checkPassword()
.done(function(r) {
    if (r) {
        // Tell the user they're logged in
    } else {
        // Tell the user their password was bad
    }
})
.fail(function(x) {
    // Tell the user something bad happened
});

अनुशंसित नहीं: सिंक्रोनस "अजाक्स" कॉल

जैसा कि मैंने उल्लेख किया है, कुछ (!) एसिंक्रोनस ऑपरेशंस में समकालिक समकक्ष हैं। मैं उनके उपयोग की वकालत नहीं करता हूं, लेकिन पूर्णता के लिए, यहां एक सिंक्रोनस कॉल करने का तरीका बताया गया है:

JQuery के बिना

यदि आप सीधे XMLHTTPRequest ऑब्जेक्ट का उपयोग करते हैं, तो तीसरे तर्क के रूप में false पास करें। .open

jQuery

यदि आप jQuery उपयोग करते हैं, तो आप async विकल्प को false सेट कर सकते हैं। ध्यान दें कि यह विकल्प jQuery 1.8 के बाद से बहिष्कृत है । फिर भी आप success कॉलबैक का उपयोग कर सकते हैं या responseText उपयोग कर सकते हैं jqXHR ऑब्जेक्ट की टेक्स्ट गुण:

function foo() {
    var jqXHR = $.ajax({
        //...
        async: false
    });
    return jqXHR.responseText;
}

यदि आप $.get , $.getJSON , आदि जैसे किसी भी अन्य jQuery अजाक्स विधि का उपयोग करते हैं, तो आपको इसे $.ajax बदलना होगा (क्योंकि आप केवल कॉन्फ़िगरेशन पैरामीटर को $.ajax पास कर सकते हैं)।

सचेत! एक तुल्यकालिक JSONP अनुरोध करना संभव नहीं है। JSONP अपनी प्रकृति से हमेशा असीमित है (इस विकल्प को भी मानने का एक और कारण नहीं है)।





javascript jsf primefaces managed-bean