javascript एसिंक्रोनस, अजाक्स अनुरोध के बजाय, मैं एक सिंक्रोनस करने के लिए jQuery कैसे प्राप्त कर सकता हूं?




ajax asynchronous (11)

यह उदाहरण है:

$.ajax({
  url: "test.html",
  async: false
}).done(function(data) {
   // Todo something..
}).fail(function(xhr)  {
   // Todo something..
});

मेरे पास एक जावास्क्रिप्ट विजेट है जो मानक विस्तार बिंदु प्रदान करता है। उनमें से एक पहले से beforecreate कार्य है। किसी वस्तु को बनाए जाने से रोकने के लिए इसे false वापसी करनी चाहिए।

मैंने jQuery का उपयोग करके इस फ़ंक्शन में एक अजाक्स कॉल जोड़ा है:

beforecreate: function (node, targetNode, type, to) {
  jQuery.get('http://example.com/catalog/create/' + targetNode.id + '?name=' + encode(to.inp[0].value),

  function (result) {
    if (result.isOk == false) 
        alert(result.message);
  });
}

लेकिन मैं अपने विजेट को आइटम बनाने से रोकना चाहता हूं, इसलिए मुझे कॉलबैक में नहीं, माँ-फ़ंक्शन में false वापसी करनी चाहिए। JQuery या किसी अन्य एपीआई का उपयोग कर एक सिंक्रनाइज़ अजाक्स अनुरोध करने का कोई तरीका है?


async: false साथ async: false आप अपने आप को एक अवरुद्ध ब्राउज़र मिलता है। एक गैर अवरुद्ध सिंक्रोनस समाधान के लिए आप निम्न का उपयोग कर सकते हैं:

ES6 / ECMAScript2015

ईएस 6 के साथ आप जनरेटर और सह पुस्तकालय का उपयोग कर सकते हैं:

beforecreate: function (node, targetNode, type, to) {
    co(function*(){  
        let result = yield jQuery.get('http://example.com/catalog/create/' + targetNode.id + '?name=' + encode(to.inp[0].value));
        //Just use the result here
    });
}

ES7

ईएस 7 के साथ आप एएससीसी का इंतजार कर सकते हैं:

beforecreate: function (node, targetNode, type, to) {
    (async function(){
        let result = await jQuery.get('http://example.com/catalog/create/' + targetNode.id + '?name=' + encode(to.inp[0].value));
        //Just use the result here
    })(); 
}

मैंने कार्सीओन द्वारा दिए गए उत्तर का उपयोग किया और JSON का उपयोग करने के लिए इसे संशोधित किया।

 function getUrlJsonSync(url){

    var jqxhr = $.ajax({
        type: "GET",
        url: url,
        dataType: 'json',
        cache: false,
        async: false
    });

    // 'async' has to be 'false' for this to work
    var response = {valid: jqxhr.statusText,  data: jqxhr.responseJSON};

    return response;
}    

function testGetUrlJsonSync()
{
    var reply = getUrlJsonSync("myurl");

    if (reply.valid == 'OK')
    {
        console.dir(reply.data);
    }
    else
    {
        alert('not valid');
    }    
}

मैंने 'JSON' के डेटा टाइप को जोड़ा और प्रतिक्रिया जेएसओएन में .responseText को बदल दिया।

मैंने लौटाई गई वस्तु की स्थिति टेक्स्ट गुण का उपयोग करके स्थिति भी पुनर्प्राप्त की। ध्यान दें, यह अजाक्स प्रतिक्रिया की स्थिति है, न कि JSON मान्य है या नहीं।

बैक-एंड को सही (अच्छी तरह से गठित) JSON में प्रतिक्रिया वापस करनी है, अन्यथा लौटाई गई वस्तु को अपरिभाषित किया जाएगा।

मूल प्रश्न का उत्तर देने पर विचार करने के दो पहलू हैं। एक अजाक्स को सिंक्रनाइज़ करने के लिए कह रहा है ( async: false को सेट करके) और दूसरा कॉलबैक फ़ंक्शन के बजाय कॉलिंग फ़ंक्शन के रिटर्न स्टेटमेंट के माध्यम से प्रतिक्रिया वापस कर रहा है।

मैंने पोस्ट के साथ भी कोशिश की और यह काम किया।

मैंने जीईटी को पोस्ट में बदल दिया और डेटा जोड़ा : पोस्टडाटा

function postUrlJsonSync(url, postdata){

    var jqxhr = $.ajax({
        type: "POST",
        url: url,
        data: postdata,
        dataType: 'json',
        cache: false,
        async: false
    });

    // 'async' has to be 'false' for this to work
    var response = {valid: jqxhr.statusText,  data: jqxhr.responseJSON};

    return response;
}

ध्यान दें कि उपरोक्त कोड केवल उस मामले में काम करता है जहां async गलत है । यदि आप async सेट करना चाहते हैं : सही लौटा ऑब्जेक्ट jqxhr AJAX कॉल रिटर्न के समय मान्य नहीं होगा, केवल बाद में जब एसिंक्रोनस कॉल समाप्त हो गया है, लेकिन प्रतिक्रिया चर सेट करने में बहुत देर हो चुकी है।


jQuery के साथ ASYNC अनुरोधों के लिए यह मेरा सरल कार्यान्वयन है। मुझे उम्मीद है कि यह किसी की मदद करेगा।

var queueUrlsForRemove = [
    'http://dev-myurl.com/image/1', 
    'http://dev-myurl.com/image/2',
    'http://dev-myurl.com/image/3',
];

var queueImagesDelete = function(){

    deleteImage( queueUrlsForRemove.splice(0,1), function(){
        if (queueUrlsForRemove.length > 0) {
            queueImagesDelete();
        }
    });

}

var deleteImage = function(url, callback) {
    $.ajax({
        url: url,
        method: 'DELETE'
    }).done(function(response){
        typeof(callback) == 'function' ? callback(response) : null;
    });
}

queueImagesDelete();

JQuery दस्तावेज़ से : आप एक सिंक्रोनस अजाक्स अनुरोध प्राप्त करने के लिए असीमित होने के लिए असीमित विकल्प निर्दिष्ट करते हैं। फिर आपकी कॉलबैक आपकी मां की कार्यवाही से पहले कुछ डेटा सेट कर सकती है।

सुझाए गए अनुसार बदला गया है कि आपका कोड कैसा दिखता है:

beforecreate: function (node, targetNode, type, to) {
    jQuery.ajax({
        url: 'http://example.com/catalog/create/' + targetNode.id + '?name=' + encode(to.inp[0].value),
        success: function (result) {
            if (result.isOk == false) alert(result.message);
        },
        async: false
    });
}

चूंकि XMLHttpReponse सिंक्रोनस ऑपरेशन को बहिष्कृत किया गया है, इसलिए मैं निम्न समाधान के साथ आया जो XMLHttpRequest लपेटता है। यह प्रकृति में असुरक्षित होने के बावजूद AJAX प्रश्नों का आदेश देता है, जो सिंगल उपयोग सीएसआरएफ टोकन के लिए बहुत उपयोगी है।

यह भी पारदर्शी है इसलिए jQuery जैसी पुस्तकालय निर्बाध रूप से संचालित होंगी।

/* wrap XMLHttpRequest for synchronous operation */
var XHRQueue = [];
var _XMLHttpRequest = XMLHttpRequest;
XMLHttpRequest = function()
{
  var xhr   = new _XMLHttpRequest();
  var _send = xhr.send;

  xhr.send = function()
  {
    /* queue the request, and if it's the first, process it */
    XHRQueue.push([this, arguments]);
    if (XHRQueue.length == 1)
      this.processQueue();
  };

  xhr.processQueue = function()
  {
    var call = XHRQueue[0];
    var xhr  = call[0];
    var args = call[1];

    /* you could also set a CSRF token header here */

    /* send the request */
    _send.apply(xhr, args);
  };

  xhr.addEventListener('load', function(e)
  {
    /* you could also retrieve a CSRF token header here */

    /* remove the completed request and if there is more, trigger the next */
    XHRQueue.shift();
    if (XHRQueue.length)
      this.processQueue();
  });

  return xhr;
};

नोट: आपको इसके कारण async का उपयोग नहीं करना चाहिए:

गेको 30.0 (फ़ायरफ़ॉक्स 30.0 / थंडरबर्ड 30.0 / सागरमोकी 2.27) से शुरू होने पर, मुख्य थ्रेड पर सिंक्रोनस अनुरोध उपयोगकर्ता अनुभव के नकारात्मक प्रभावों के कारण बहिष्कृत किए गए हैं।

क्रोम कंसोल में इसके बारे में भी चेतावनी देता है:

मुख्य थ्रेड पर सिंक्रोनस XMLHttpRequest को अंतिम उपयोगकर्ता के अनुभव के हानिकारक प्रभावों के कारण बहिष्कृत किया गया है। अधिक सहायता के लिए, https://xhr.spec.whatwg.org/

यदि आप ऐसा कुछ कर रहे हैं तो यह आपके पृष्ठ को तोड़ सकता है क्योंकि यह किसी भी दिन काम करना बंद कर सकता है।

यदि आप ऐसा करना चाहते हैं जो अभी भी ऐसा लगता है कि यह सिंक्रोनस है लेकिन फिर भी ब्लॉक नहीं करता है तो आपको एसिंक / प्रतीक्षा का उपयोग करना चाहिए और शायद कुछ एजेक्स भी जो कि नए Fetch API जैसे वादों पर आधारित है

async function foo() {
  var res = await fetch(url)
  console.log(res.ok)
  var json = await res.json()
  console.log(json)
}

सबसे पहले हमें समझना चाहिए कि जब हम $ .ajax का उपयोग करते हैं और जब हम $ .get / $। पोस्ट का उपयोग करते हैं

जब हमें AJAX अनुरोध पर निम्न स्तर नियंत्रण की आवश्यकता होती है जैसे अनुरोध हेडर सेटिंग्स, कैशिंग सेटिंग्स, सिंक्रोनस सेटिंग्स इत्यादि। तो हमें $ .ajax के लिए जाना चाहिए।

$ .get / $। पोस्ट: जब हमें AJAX अनुरोध पर निम्न स्तर नियंत्रण की आवश्यकता नहीं होती है। केवल सर्वर को डेटा को सरल / पोस्ट करें। यह शॉर्टेंड है

$.ajax({
  url: url,
  data: data,
  success: success,
  dataType: dataType
});

और इसलिए हम $ .get / $। पोस्ट के साथ अन्य सुविधाओं (सिंक, कैश इत्यादि) का उपयोग नहीं कर सकते हैं।

इसलिए AJAX अनुरोध पर निम्न स्तर नियंत्रण (सिंक, कैश, आदि) के लिए, हमें $ .ajax के लिए जाना चाहिए

 $.ajax({
     type: 'GET',
      url: url,
      data: data,
      success: success,
      dataType: dataType,
      async:false
    });

इन सभी उत्तरों ने उस बिंदु को याद किया है जो अजाक्स कॉल के साथ अजाक्स कॉल कर रहा है: झूठा ब्राउज़र को अजाक्स अनुरोध पूरा होने तक लटका देगा। फ्लो कंट्रोल लाइब्रेरी का उपयोग ब्राउज़र को लटकाने के बिना इस समस्या को हल करेगा। Frame.js साथ एक उदाहरण यहां दिया गया है:

beforecreate: function(node,targetNode,type,to) {

    Frame(function(next)){

        jQuery.get('http://example.com/catalog/create/', next);
    });

    Frame(function(next, response)){

        alert(response);
        next();
    });

    Frame.init();
}

ध्यान रखें कि यदि आप एक क्रॉस-डोमेन अजाक्स कॉल कर रहे हैं ( JSONP का उपयोग करके) - आप इसे सिंक्रनाइज़ नहीं कर सकते हैं , तो async ध्वज को jQuery द्वारा अनदेखा कर दिया जाएगा।

$.ajax({
    url: "testserver.php",
    dataType: 'jsonp', // jsonp
    async: false //IGNORED!!
});

जेएसओएनपी-कॉल के लिए आप इसका उपयोग कर सकते हैं:

  1. अजाक्स-अपने डोमेन पर कॉल करें - और क्रॉस-डोमेन कॉल सर्वर-साइड करें
  2. अपने कोड को असीमित रूप से काम करने के लिए बदलें
  3. Frame.js जैसे एक "फ़ंक्शन अनुक्रमक" लाइब्रेरी का उपयोग करें (यह answer )
  4. निष्पादन को अवरुद्ध करने के बजाय यूआई को अवरुद्ध करें (यह answer ) (मेरा पसंदीदा तरीका)

उत्कृष्ट समाधान! मैंने देखा कि जब मैंने इसे लागू करने की कोशिश की तो अगर मैंने सफलता खंड में एक मूल्य वापस कर दिया, तो यह अपरिभाषित के रूप में वापस आया। मुझे इसे एक चर में स्टोर करना था और उस चर को वापस करना था। यह वह तरीका है जिसके साथ मैं आया था:

function getWhatever() {
  // strUrl is whatever URL you need to call
  var strUrl = "", strReturn = "";

  jQuery.ajax({
    url: strUrl,
    success: function(html) {
      strReturn = html;
    },
    async:false
  });

  return strReturn;
}




asynchronous