අසමමුහුර්ත ඇමතුමකින් ප්‍රතිචාරය ලබා දෙන්නේ කෙසේද?


5513

මට fooඅජැක්ස් ඉල්ලීමක් කරන ශ්‍රිතයක් ඇත. ප්‍රතිචාරය ලබා fooදෙන්නේ කෙසේද?

මම successඇමතුමෙන් ආපසු ලබා දීමට උත්සාහ කළෙමි , එසේම ශ්‍රිතය තුළ දේශීය විචල්‍යයකට ප්‍රතිචාරය ලබා දී එය නැවත ලබා දීමට උත්සාහ කළෙමි , නමුත් ඒ කිසිවක් සත්‍ය වශයෙන්ම ප්‍රතිචාරය නොදක්වයි.

function foo() {
    var result;

    $.ajax({
        url: '...',
        success: function(response) {
            result = response;
            // return response; // <- I tried that one as well
        }
    });

    return result;
}

var result = foo(); // It always ends up being `undefined`.

Answers:


5705

Examples විවිධ උදාහරණ සහිත අසින්ක් හැසිරීම පිළිබඳ වඩාත් පොදු පැහැදිලි කිරීමක් සඳහා, කරුණාකර බලන්න ශ්‍රිතයක් තුළ මා වෙනස් කළ පසු මගේ විචල්‍යය වෙනස් නොවන්නේ ඇයි? - අසමමුහුර්ත කේත යොමුව

Already ඔබ දැනටමත් ගැටලුව තේරුම් ගෙන ඇත්නම්, පහත ඇති විසඳුම් වෙත යන්න.

ගැටලුව වන්නේ

මෙම A දී Ajax සඳහා කි්රයා අසමමිතික . ඒ කියන්නේ ඉල්ලීම යැවීම (හෝ ප්‍රතිචාරය ලැබීම) සාමාන්‍ය ක්‍රියාත්මක කිරීමේ ප්‍රවාහයෙන් ඉවත් කර ගැනීමයි. ඔබගේ උදාහරණයේ දී, $.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();දෙන තෙක් බලා සිටිය යුතුය.

අසමමුහුර්ත

ඔබ නැවතත් ඔබේ මිතුරා අමතන්නේ එකම හේතුව නිසාය. නමුත් මේ වතාවේ ඔබ ඔහුට කියන්නේ ඔබ කඩිමුඩියේ සිටින බවත් ඔහු ඔබේ ජංගම දුරකථනයට නැවත ඇමතිය යුතු බවත්ය. ඔබ එල්ලී, නිවසින් පිට වී ඔබ කිරීමට සැලසුම් කළ ඕනෑම දෙයක් කරන්න. ඔබේ මිතුරා ඔබට නැවත ඇමතුමක් ලබා දුන් පසු, ඔහු ඔබට ලබා දුන් තොරතුරු සමඟ කටයුතු කරයි.

ඔබ අජැක්ස් ඉල්ලීමක් කරන විට සිදුවන්නේ එයයි.

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

ප්‍රතිචාරය බලාපොරොත්තුවෙන් සිටිනවා වෙනුවට, ක්‍රියාත්මක කිරීම වහාම ක්‍රියාත්මක වන අතර අජැක්ස් ඇමතුමෙන් පසුව ප්‍රකාශය ක්‍රියාත්මක වේ. අවසානයේ ප්රතිචාරය ලබා ගැනීම සඳහා, ඔබ විසින් ප්රතිචාරයක් නොලැබුණු බව වරක් කියනු ලබන උත්සවයකට, ලබා callback (දැනුම් දෙයක්? ඇමතුමක් ආපසු ?). එම ඇමතුමෙන් පසුව එන ඕනෑම ප්‍රකාශයක් ඇමතුම ලබා ගැනීමට පෙර ක්‍රියාත්මක වේ.


විසඳුම්)

ජාවාස්ක්‍රිප්ට්හි අසමමුහුර්ත ස්වභාවය වැලඳ ගන්න! සමහර අසමමුහුර්ත මෙහෙයුම් සමමුහුර්ත සගයන් සපයන අතර ("අජැක්ස්" ද එසේ වේ), සාමාන්‍යයෙන් ඒවා බ්‍රවුසර සන්දර්භය තුළ භාවිතා කිරීම අධෛර්යමත් කරයි.

ඇයි ඔබ අහන්නේ නරක?

ජාවාස්ක්‍රිප්ට් බ්‍රව්සරයේ UI නූල් තුළ ක්‍රියාත්මක වන අතර ඕනෑම දිගු ක්‍රියාවලියක් UI අගුළු දමනු ඇත, එය ප්‍රතිචාර නොදක්වයි. මීට අමතරව, ජාවාස්ක්‍රිප්ට් ක්‍රියාත්මක කිරීමේ වේලාවට ඉහළ සීමාවක් ඇති අතර බ්‍රවුසරය පරිශීලකයාගෙන් විමසනුයේ ක්‍රියාත්මක කිරීම දිගටම කරගෙන යා යුතුද නැද්ද යන්නයි.

මේ සියල්ල ඇත්තෙන්ම නරක පරිශීලක අත්දැකීමකි. සෑම දෙයක්ම හොඳින් ක්‍රියාත්මක වේද නැද්ද යන්න පරිශීලකයාට පැවසිය නොහැක. තවද, මන්දගාමී සම්බන්ධතාවයක් ඇති පරිශීලකයින්ට එහි බලපෑම වඩාත් නරක වනු ඇත.

පහත දැක්වෙන පරිදි අපි එකිනෙකට ඉහළින් ගොඩනඟන විවිධ විසඳුම් තුනක් දෙස බලමු:

  • async/await(ES2017 + සමඟ පොරොන්දු, ඔබ ප්‍රවාහකයෙකු හෝ පුනර්ජනකය භාවිතා කරන්නේ නම් පැරණි බ්‍රව්සර් වලින් ලබාගත හැකිය)
  • ඇමතුම් ආපසු (නෝඩයේ ජනප්‍රියයි)
  • then()(ES2015 + සමඟ පොරොන්දු , ඔබ බොහෝ පොරොන්දු පුස්තකාලවලින් එකක් භාවිතා කරන්නේ නම් පැරණි බ්‍රව්සර් වලින් ලබාගත හැකිය)

මේ තුනම වත්මන් බ්‍රව්සර් වලින් ලබා ගත හැකි අතර 7+ නෝඩ් ඇත.


ES2017 +: සමඟ පොරොන්දු async/await

2017 දී නිකුත් කරන ලද ECMAScript අනුවාදය අසමමුහුර්ත කාර්යයන් සඳහා සින්ටැක්ස් මට්ටමේ සහාය හඳුන්වා දුන්නේය . ද සහාය ඇතිව asyncහා await, ඔබ "සමමුහුර්ත ශෛලිය" තුළ අසමමිතික ලියන්න පුළුවන්. කේතය තවමත් අසමමුහුර්තයි, නමුත් කියවීම / තේරුම් ගැනීම පහසුය.

async/awaitපොරොන්දු මත ගොඩනැඟේ: asyncශ්‍රිතයක් සෑම විටම පොරොන්දුවක් ලබා දෙයි. awaitපොරොන්දුවක් "ලිහා ගැනීම" සහ පොරොන්දුව ප්‍රතික්ෂේප කළ හොත් පොරොන්දුව විසඳා ඇති වටිනාකමට හෝ දෝෂයක් ඇතිවීමට හේතු වේ.

වැදගත්: ඔබට භාවිතා කළ හැක්කේ ශ්‍රිතයක් awaitතුළ පමණි async. මේ මොහොතේ, ඉහළ මට්ටමේ awaitතවමත් සහාය නොදක්වන බැවින් සන්දර්භයක් ආරම්භ කිරීම සඳහා ඔබට අසමමුහුර්ත IIFE ( ක්ෂණිකව ආයාචනා කරන ලද ක්‍රියාකාරී ප්‍රකාශනය ) සෑදිය යුතුය async.

MDN ගැන asyncසහ ඔබට වැඩිදුර කියවිය හැකිය 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;
  }
}

// Start an IIFE to use `await` at the top level
(async function(){
  let books = await getAllBooks();
  console.log(books);
})();

වත්මන් බ්‍රව්සරය සහ නෝඩ් අනුවාද සඳහා සහය දක්වයි async/await. ඔබේ කේතය ප්‍රතිජනක යන්ත්‍රයේ ආධාරයෙන් (හෝ බාබෙල් වැනි පුනර්ජනන යන්ත්‍ර භාවිතා කරන මෙවලම්) ES5 බවට පරිවර්තනය කිරීමෙන් ඔබට පැරණි පරිසරයන්ට සහාය විය හැකිය .


ඇමතුම් ආපසු භාර ගැනීමට කාර්යයන් වලට ඉඩ දෙන්න

ඇමතුමක් යනු හුදෙක් වෙනත් ශ්‍රිතයකට ලබා දෙන ශ්‍රිතයකි. අනෙක් ශ්‍රිතයට එය සූදානම් වූ විට සම්මත කරන ලද ශ්‍රිතය ඇමතිය හැකිය. අසමමුහුර්ත ක්‍රියාවලියක සන්දර්භය තුළ, අසමමුහුර්ත ක්‍රියාවලිය සිදු කරන සෑම අවස්ථාවකදීම ඇමතුම් ලබා ගැනීම කැඳවනු ලැබේ. සාමාන්‍යයෙන්, ප්‍රති result ලය ඇමතුම වෙත යවනු ලැබේ.

ප්‍රශ්නයේ උදාහරණයේ දී, ඔබට 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
    });
}

callbackfooඑය අප අමතන විට අප විසින් ලබා දෙන ශ්‍රිතයට යොමු වන අතර අපි එය සරලවම ලබා දෙමු success. එනම්, අජැක්ස් ඉල්ලීම සාර්ථක වූ පසු, $.ajaxඇමතුමට callbackප්‍රතිචාරය ඇමතීම සහ සම්මත කිරීම සිදු කරනු ඇත (එය අප ඇමතීම resultඅර්ථ දැක්වූයේ මේ නිසාය).

ඇමතුම වෙත යැවීමට පෙර ඔබට ප්‍රතිචාරය සැකසිය හැක:

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

පෙනෙන ආකාරයට වඩා කෝල්බැක් භාවිතයෙන් කේත ලිවීම පහසුය. සියල්ලට පසු, බ්‍රව්සරයේ ජාවාස්ක්‍රිප්ට් දැඩි ලෙස සිදුවීම් මත පදනම් වේ (DOM සිදුවීම්). අජැක්ස් ප්‍රතිචාරය ලැබීම සිදුවීමක් මිස වෙන කිසිවක් නොවේ.
ඔබට තෙවන පාර්ශවීය කේතය සමඟ වැඩ කිරීමට සිදුවන විට දුෂ්කරතා ඇතිවිය හැකි නමුත් යෙදුම් ප්‍රවාහය ගැන සිතීමෙන් බොහෝ ගැටලු විසඳිය හැකිය.


ES2015 +: එවකට පොරොන්දු ()

මෙම පොරොන්දුව API සම්මතයන් 6 (ES2015) නව විශේෂාංගයක්, නමුත් එය යහපත් කල් බ්රවුසරය සහාය දැනටමත්. සම්මත පොරොන්දු ඒපීඅයි ක්‍රියාත්මක කරන සහ අසමමුහුර්ත කාර්යයන් (උදා: බ්ලූබර්ඩ් ) භාවිතය සහ සංයුතිය ලිහිල් කිරීම සඳහා අතිරේක ක්‍රම සපයන බොහෝ පුස්තකාල තිබේ.

පොරොන්දු අනාගත වටිනාකම් සඳහා බහාලුම් වේ . පොරොන්දුවට වටිනාකම ලැබුණු විට (එය විසඳනු ලැබේ ) හෝ එය අවලංගු කළ විට ( ප්‍රතික්ෂේප කරනු ලැබේ ), මෙම අගයට ප්‍රවේශ වීමට කැමති එහි සියලුම “සවන්දෙන්නන්ට” එය දැනුම් දෙයි.

සරල ඇමතුම් වලට වඩා වැඩි වාසියක් නම්, ඒවා ඔබේ කේතය විසන්ධි කිරීමට ඉඩ දෙන අතර ඒවා රචනා කිරීමට පහසු වේ.

පොරොන්දුවක් භාවිතා කිරීම පිළිබඳ සරල උදාහරණයක් මෙන්න:

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

පොරොන්දු වූ සියලු වාසි විස්තර කිරීම මෙම පිළිතුරේ සීමාවෙන් ඔබ්බට ය, නමුත් ඔබ නව කේතයක් ලියන්නේ නම්, ඔබ ඒවා බැරෑරුම් ලෙස සලකා බැලිය යුතුය. ඔවුන් ඔබේ කේතය විශාල සාරාංශයක් හා වෙන් කිරීමක් සපයයි.

පොරොන්දු පිළිබඳ වැඩි විස්තර: HTML5 පාෂාණ - ජාවාස්ක්‍රිප්ට් පොරොන්දු

පැති සටහන: jQuery හි විලම්බිත වස්තු

විලම්බිත වස්තූන් යනු jQuery හි අභිරුචි පොරොන්දු ක්‍රියාත්මක කිරීමයි (පොරොන්දු API ප්‍රමිතිකරණය කිරීමට පෙර). ඔවුන් පොරොන්දු මෙන් හැසිරෙන නමුත් තරමක් වෙනස් 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 Ajax විලම්බිත වස්තුව, සේවාදායකය වෙතින් ප්රතිචාරය පැමිණේ. ඒ කියන්නේ 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 ලබා ගත හැකිය, නැතහොත් jqXHR වස්තුවෙහිresponseText දේපල වෙත පිවිසිය හැකිය :

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

ඔබ වැනි වෙනත් ඕනෑම jQuery Ajax ක්රමය භාවිතා කරන්නේ නම් $.get, $.getJSONආදිය, ඔබට එය වෙනස් කිරීමට ඇති $.ajax(ඔබ පමණක් මානකරණ පරාමිතික ඇතුල් වෙන නිසා $.ajax).

දැනුම්දීම! සමමුහුර්ත JSONP ඉල්ලීමක් කළ නොහැක. JSONP එහි ස්වභාවය අනුව සෑම විටම අසමමුහුර්ත වේ (මෙම විකල්පය පවා නොසැලකීමට තවත් එක් හේතුවක්).


74
Om පොමී: ඔබට jQuery භාවිතා කිරීමට අවශ්‍ය නම්, ඔබ එය ඇතුළත් කළ යුතුය. කරුණාකර docs.jquery.com/Tutorials :Getting_Started_with_jQuery වෙත යොමු වන්න .
ෆීලික්ස් ක්ලින්ග්

11
විසඳුම 1, උප jQuery හි, මට මෙම රේඛාව තේරුම් ගත නොහැකි විය: If you use any other jQuery AJAX method, such as $.get, $.getJSON, etc., you have them to $.ajax.(ඔව්, මගේ නික් මේ අවස්ථාවේ දී ඉතා උත්ප‍්‍රාසාත්මක බව මට වැටහී ඇත)
cssyphus

32
@gibberish: ම්ම්ම්, එය වඩාත් පැහැදිලි කරන්නේ කෙසේදැයි මම නොදනිමි. foo( foo(function(result) {....});) වෙත ශ්‍රිතයක් ලබා දෙන ආකාරය ඔබ දකිනවාද ? resultමෙම ශ්‍රිතය තුළ භාවිතා වන අතර එය අජැක්ස් ඉල්ලීමේ ප්‍රතිචාරයයි. මෙම ශ්රිතය වෙත යොමු කිරීමට, foo පළමු පරාමිතිය ලෙස හැඳින්වේ callbackඅනුයුත්ත successවෙනුවට නිර්නාමික කාර්යය. එබැවින්, ඉල්ලීම සාර්ථක වූ විට $.ajaxඅමතන්න callback. මම එය තව ටිකක් පැහැදිලි කිරීමට උත්සාහ කළෙමි.
ෆීලික්ස් ක්ලින්ග්

43
මෙම ප්‍රශ්නය සඳහා වන කතාබහ මියගොස් ඇති බැවින් ලුහු lined ු සටහන් යෝජනා කළ යුත්තේ කොතැනදැයි මට විශ්වාස නැත, නමුත් මම යෝජනා කරමි: 1) සමමුහුර්ත කොටස එය කරන්නේ කෙසේද යන්න පිළිබඳ කේත උදාහරණයකින් තොරව එය නරක ඇයි යන්න පිළිබඳ සරල සාකච්ඡාවකට වෙනස් කරන්න. 2) ජාවාස්ක්‍රිප්ට් ඉගෙන ගන්නා අයට අනුගමනය කිරීම තරමක් පහසු වනු ඇතැයි මා සිතන, වඩාත් නම්‍යශීලී විලම්බිත ප්‍රවේශයක් පමණක් පෙන්වීමට ඇමතුම් ආපසු ගැනීමේ උදාහරණ ඉවත් කරන්න / ඒකාබද්ධ කරන්න.
ක්‍රිස් මොස්චිනි

14
Ess ජෙසී: මම හිතන්නේ ඔබ පිළිතුරේ එම කොටස වරදවා වටහාගෙන ඇත. ඔබට $.getJSONඅජැක්ස් ඉල්ලීම සමමුහුර්ත වීමට අවශ්‍ය නම් ඔබට භාවිතා කළ නොහැක . කෙසේ වෙතත්, ඉල්ලීම සමමුහුර්ත වීමට ඔබට අවශ්‍ය නොවිය යුතුය, එබැවින් එය අදාළ නොවේ. පිළිතුරෙහි කලින් විස්තර කර ඇති පරිදි, ප්‍රතිචාරය හැසිරවීමට ඔබ ඇමතුම් හෝ පොරොන්දු භාවිතා කළ යුතුය.
ෆීලික්ස් ක්ලින්ග්

1071

ඔබ කරන්නේ නම් නෑ ඔබගේ කේතය දී jQuery භාවිතා, මෙම පිළිතුර ඔබ සඳහා

ඔබේ කේතය මේ හා සමාන දෙයක් විය යුතුය:

function foo() {
    var httpRequest = new XMLHttpRequest();
    httpRequest.open('GET', "/echo/json");
    httpRequest.send();
    return httpRequest.responseText;
}

var result = foo(); // always ends up being 'undefined'

AJAX සඳහා jQuery භාවිතා කරන පුද්ගලයින් සඳහා පිළිතුරක් ලිවීමට ෆීලික්ස් ක්ලින්ග් ඉතා හොඳ කාර්යයක් ඉටු කළේය, එසේ නොවන පුද්ගලයින් සඳහා විකල්පයක් සැපයීමට මම තීරණය කළෙමි.

( සටහන, නව fetchAPI, කෝණික හෝ පොරොන්දු භාවිතා කරන්නන් සඳහා මම තවත් පිළිතුරක් පහතින් එකතු කර ඇත්තෙමි )


ඔබ මුහුණ දෙන දේ

මෙය අනෙක් පිළිතුරෙන් "ගැටලුව පැහැදිලි කිරීම" පිළිබඳ කෙටි සාරාංශයකි, මෙය කියවීමෙන් පසු ඔබට විශ්වාස නැත්නම්, එය කියවන්න.

AJAX හි A යනු අසමමුහුර්ත වේ. ඒ කියන්නේ ඉල්ලීම යැවීම (හෝ ප්‍රතිචාරය ලැබීම) සාමාන්‍ය ක්‍රියාත්මක කිරීමේ ප්‍රවාහයෙන් ඉවත් කර ගැනීමයි. ඔබගේ උදාහරණයේ දී, .sendවහාම ආපසු පැමිණීම සහ ඊළඟ ප්‍රකාශය, return result;ඔබ successඇමතුම ලෙස හැඳින්වූ ශ්‍රිතය ඇමතීමට පෙර ක්‍රියාත්මක කරනු ලැබේ.

මෙයින් අදහස් කරන්නේ ඔබ නැවත පැමිණෙන විට, ඔබ අර්ථ දක්වා ඇති සවන්දෙන්නන් තවම ක්‍රියාත්මක කර නොමැති බවයි, එයින් අදහස් වන්නේ ඔබ ආපසු එන වටිනාකම නිර්වචනය කර නොමැති බවයි.

මෙන්න සරල ප්‍රතිසමයක්

function getFive(){ 
    var a;
    setTimeout(function(){
         a=5;
    },10);
    return a;
}

(ෆෙඩෙල්)

වටිනාකම aආපසු වේ undefinedසිට a=5කොටසක් තවමත් ක්රියාවට නගා නැත. AJAX මේ ආකාරයට ක්‍රියා කරයි, ඔබේ බ්‍රව්සරයට එම වටිනාකම කුමක්දැයි පැවසීමට සේවාදායකයාට අවස්ථාව ලැබීමට පෙර ඔබ එම අගය නැවත ලබා දෙයි.

මෙම ගැටළුවට ඇති විය හැකි එක් විසඳුමක් වන්නේ නැවත ක්‍රියාශීලීව කේත කිරීම, ගණනය කිරීම අවසන් වූ විට කළ යුතු දේ ඔබේ වැඩසටහනට පැවසීමයි.

function onComplete(a){ // When the code completes, do this
    alert(a);
}

function getFive(whenDone){ 
    var a;
    setTimeout(function(){
         a=5;
         whenDone(a);
    },10);
}

මෙය CPS ලෙස හැඳින්වේ . මූලික වශයෙන්, අපි getFiveඑය ක්‍රියාවට නංවන විට එය සිදු වූ විට, සිදුවීමක් අවසන් වූ විට ප්‍රතික්‍රියා කරන්නේ කෙසේදැයි අපි අපගේ කේතයට කියමු (අපගේ AJAX ඇමතුම වැනි, හෝ මේ අවස්ථාවේ කල් ඉකුත් වීම).

භාවිතය වනුයේ:

getFive(onComplete);

තිරය ​​වෙත "5" අනතුරු ඇඟවිය යුතු. (ෆිදෙල්) .

හැකි විසඳුම්

මෙය විසඳීමට මූලික වශයෙන් ක්‍රම දෙකක් තිබේ:

  1. AJAX ඇමතුම සමමුහුර්ත කරන්න (එය SJAX ලෙස හැඳින්වීමට ඉඩ දෙන්න).
  2. ඇමතුම් ආපසු ගැනීම සමඟ නිසි ලෙස ක්‍රියා කිරීමට ඔබේ කේතය ප්‍රතිව්‍යුහගත කරන්න.

1. සමමුහුර්ත අජැක්ස් - එය නොකරන්න !!

සමමුහුර්ත AJAX සඳහා, එය නොකරන්න! ෆීලික්ස්ගේ පිළිතුර එය නරක අදහසක් වන්නේ මන්ද යන්න පිළිබඳව බලවත් තර්ක කිහිපයක් මතු කරයි. එය සාරාංශගත කිරීම සඳහා, සේවාදායකයා ප්‍රතිචාරය ලබා දෙන තෙක් පරිශීලකයාගේ බ්‍රව්සරය කැටි කර ඉතා නරක පරිශීලක අත්දැකීමක් නිර්මාණය කරයි. එම්ඩීඑන් වෙතින් ලබාගත් තවත් කෙටි සාරාංශයක් මෙන්න:

XMLHttpRequest සමමුහුර්ත හා අසමමුහුර්ත සන්නිවේදනයන් සඳහා සහය දක්වයි. කෙසේ වෙතත්, පොදුවේ ගත් කල, කාර්ය සාධන හේතූන් මත සමමුහුර්ත ඉල්ලීම් සඳහා අසමමුහුර්ත ඉල්ලීම් වඩාත් සුදුසු වේ.

කෙටියෙන් කිවහොත්, සමමුහුර්ත ඉල්ලීම් කේතය ක්‍රියාත්මක කිරීම අවහිර කරයි ... ... මෙය බරපතල ගැටළු ඇති කළ හැකිය ...

ඔබට එය කිරීමට සිදුවුවහොත් , ඔබට ධජයක් පසු කළ හැකිය: මෙන්න කෙසේද:

var request = new XMLHttpRequest();
request.open('GET', 'yourURL', false);  // `false` makes the request synchronous
request.send(null);

if (request.status === 200) {// That's HTTP for 'ok'
  console.log(request.responseText);
}

2. ප්‍රතිව්‍යුහගත කිරීමේ කේතය

ඔබගේ ශ්‍රිතයට ඇමතුමක් ලබා ගැනීමට ඉඩ දෙන්න. උදාහරණ කේතය fooඇමතුමක් ලබා ගැනීම සඳහා කළ හැකිය. සම්පුර්ණ වූ විට ප්‍රතික්‍රියා කරන්නේ කෙසේදැයි අපි අපගේ කේතයට කියමුfoo .

ඒ නිසා:

var result = foo();
// code that depends on `result` goes here

බවට පත්වේ:

foo(function(result) {
    // code that depends on `result`
});

මෙන්න අපි නිර්නාමික ශ්‍රිතයක් සම්මත කළෙමු, නමුත් අපට පහසුවෙන් පවතින ශ්‍රිතයක් වෙත යොමු කිරීමක් කළ හැකිය.

function myHandler(result) {
    // code that depends on `result`
}
foo(myHandler);

මෙවැනි ඇමතුම් ආපසු ගැනීමේ සැලසුම සිදු කරන්නේ කෙසේද යන්න පිළිබඳ වැඩි විස්තර සඳහා, ෆීලික්ස්ගේ පිළිතුර පරීක්ෂා කරන්න.

දැන්, ඒ අනුව ක්‍රියා කිරීම සඳහා foo යන්න නිර්වචනය කරමු

function foo(callback) {
    var httpRequest = new XMLHttpRequest();
    httpRequest.onload = function(){ // when the request is loaded
       callback(httpRequest.responseText);// we're calling our method
    };
    httpRequest.open('GET', "/echo/json");
    httpRequest.send();
}

(ෆෙඩල්)

AJAX සාර්ථකව සම්පුර්ණ වූ විට ක්‍රියාත්මක කිරීම සඳහා වූ ක්‍රියාවක් පිළිගැනීමට අපි දැන් කටයුතු කර ඇත්තෙමු, ප්‍රතිචාර තත්ත්වය 200 ක් නොවේදැයි පරීක්ෂා කර බලා ඒ අනුව ක්‍රියා කිරීමෙන් අපට මෙය තවදුරටත් දීර් can කළ හැකිය (අසමත් හසුරුවන්නෙකු නිර්මාණය කරන්න). අපගේ ගැටලුව effectively ලදායී ලෙස විසඳීම.

ඔබට මෙය තේරුම් ගැනීමට තවමත් අපහසු නම්, එම්ඩීඑන් හි ඇජැක්ස් ආරම්භක මාර්ගෝපදේශය කියවන්න .


20
"සමමුහුර්ත ඉල්ලීම් කේතය ක්‍රියාත්මක කිරීම අවහිර කරන අතර මතකය හා සිදුවීම් කාන්දු විය හැක" සමමුහුර්ත ඉල්ලීමක් මතකය කාන්දු වන්නේ කෙසේද?
මැතිව් ජී

10
@MatthewG මම එක හොදයි එය මත සතුරෝද එකතු මෙම ප්රශ්නය , මම මම මාළු හැකි දේ පෙනෙනු ඇත. මම මධ්‍යන්‍ය වේලාවෙන් පිළිතුරෙන් උපුටා දැක්වීම ඉවත් කරමි.
බෙන්ජමින් ග ru න්බෝම්

17
හුදෙක් පරිශීලනය සඳහා, XHR 2 අපට භාවිතා කිරීමට ඉඩ දෙයි onloadවිට පමණක් ගිනි කරන හැසිරවීම, readyStateවේ 4. ඇත්ත වශයෙන්ම, එය IE8 හි සහය නොදක්වයි. (iirc, තහවුරු කිරීම අවශ්‍ය විය හැකිය.)
ෆ්ලෝරියන් මාගයින්

9
ඇමතුමක් ලෙස නිර්නාමික ශ්‍රිතයක් සම්මත කරන්නේ කෙසේද යන්න පිළිබඳ ඔබේ පැහැදිලි කිරීම වලංගු නමුත් නොමඟ යවන සුළුය. උදාහරණය var bar = foo (); විචල්‍යයක් නිර්වචනය කිරීමට ඉල්ලා සිටින අතර, ඔබ යෝජනා කළ foo (functim () {}); තීරුව අර්ථ දක්වන්නේ නැත
රොබී ඇවරිල්

396

XMLHttpRequest 2 (පළමුවෙන්ම බෙන්ජමින් ග ru න්බෝම් සහ ෆීලික්ස් ක්ලින්ග්ගේ පිළිතුරු කියවන්න)

ඔබ jQuery භාවිතා නොකරන්නේ නම් සහ නවීන බ්‍රව්සර්වල මෙන්ම ජංගම බ්‍රව්සර්වල ද ක්‍රියා කරන ලස්සන කෙටි XMLHttpRequest 2 අවශ්‍ය නම් මම එය මේ ආකාරයෙන් භාවිතා කිරීමට යෝජනා කරමි:

function ajax(a, b, c){ // URL, callback, just a placeholder
  c = new XMLHttpRequest;
  c.open('GET', a);
  c.onload = b;
  c.send()
}

ඔබට පෙනෙන පරිදි:

  1. ලැයිස්තුගත කර ඇති අනෙකුත් සියලුම කාර්යයන්ට වඩා එය කෙටි ය.
  2. ඇමතුම සෘජුවම සකසා ඇත (එබැවින් අමතර අනවශ්‍ය වසා දැමීම් නොමැත).
  3. එය නව ඔන්ලෝඩ් භාවිතා කරයි (එබැවින් ඔබ රෙඩ්ස්ටේට් සහ ඇන්ඩ් තත්ත්වය පරීක්ෂා කළ යුතු නැත)
  4. XMLHttpRequest 1 කරදරකාරී වන බව මට මතක නැති තවත් අවස්ථා කිහිපයක් තිබේ.

මෙම අජැක්ස් ඇමතුමේ ප්‍රතිචාරය ලබා ගැනීමට ක්‍රම දෙකක් තිබේ (තුනක් XMLHttpRequest var නම භාවිතා කරමින්):

සරලම:

this.response

හෝ කිසියම් හේතුවක් නිසා ඔබ bind()පන්තියකට ඇමතුමක් ලබා දෙන්නේ නම්:

e.target.response

උදාහරණයක්:

function callback(e){
  console.log(this.response);
}
ajax('URL', callback);

නැතහොත් (ඉහත එක වඩා හොඳ නිර්නාමික කාර්යයන් සැමවිටම ගැටළුවක් වේ):

ajax('URL', function(e){console.log(this.response)});

කිසිවක් පහසු නැත.

දැන් සමහර අය කියනු ඇත්තේ onreadystatechange හෝ XMLHttpRequest විචල්‍ය නාමය භාවිතා කිරීම වඩා හොඳ බවයි. ඒක වැරදියි.

පරීක්ෂා කරන්න XMLHttpRequest උසස් විශේෂාංග

එය සියලු නවීන බ්‍රව්සර් සඳහා සහය විය. XMLHttpRequest 2 පවතින බැවින් මම මෙම ප්‍රවේශය භාවිතා කරන බැවින් මට තහවුරු කළ හැකිය. මා භාවිතා කරන සියලුම බ්‍රව්සර්වල කිසිඳු ආකාරයක ගැටලුවක් මට නොතිබුණි.

onreadystatechange ප්‍රයෝජනවත් වන්නේ ඔබට රාජ්‍ය 2 හි ශීර්ෂයන් ලබා ගැනීමට අවශ්‍ය නම් පමණි.

XMLHttpRequestවිචල්ය නාමය භාවිතා කිරීම තවත් විශාල දෝෂයකි, මන්දයත් ඔබට ඕල්ලෝඩ් / ඕරෙඩිස්ටේට්චේන්ජ් වසා දැමීම් තුළ නැවත ඇමතුම ක්රියාත්මක කිරීමට අවශ්ය බැවින් ඔබට එය අහිමි විය.


දැන් ඔබට පෝස්ට් සහ ෆෝම් ඩේටා භාවිතයෙන් වඩාත් සංකීර්ණ යමක් අවශ්‍ය නම් ඔබට පහසුවෙන් මෙම ක්‍රියාව දිගු කළ හැකිය:

function x(a, b, e, d, c){ // URL, callback, method, formdata or {key:val},placeholder
  c = new XMLHttpRequest;
  c.open(e||'get', a);
  c.onload = b;
  c.send(d||null)
}

නැවතත් ... එය ඉතා කෙටි කාර්යයකි, නමුත් එය ලබාගෙන පළ කරයි.

භාවිතයට උදාහරණ:

x(url, callback); // By default it's get so no need to set
x(url, callback, 'post', {'key': 'val'}); // No need to set post data

නැතහොත් සම්පූර්ණ ආකෘති අංගයක් ( document.getElementsByTagName('form')[0]) පසු කරන්න:

var fd = new FormData(form);
x(url, callback, 'post', fd);

හෝ අභිරුචි අගයන් කිහිපයක් සකසන්න:

var fd = new FormData();
fd.append('key', 'val')
x(url, callback, 'post', fd);

ඔබට පෙනෙන පරිදි මම සමමුහුර්තකරණය ක්‍රියාත්මක නොකළේය ... එය නරක දෙයකි.

එසේ පවසා ... ඇයි එය පහසු ක්‍රමයක් නොකරන්නේ?


විවරණයේ සඳහන් කර ඇති පරිදි දෝෂ සහ සමමුහුර්ත භාවිතය පිළිතුරේ ලක්ෂ්‍යය මුළුමනින්ම බිඳ දමයි. නිසි ආකාරයෙන් අජැක්ස් භාවිතා කිරීමට කදිම කෙටි ක්‍රමයක් කුමක්ද?

දෝෂ හසුරුවන්නා

function x(a, b, e, d, c){ // URL, callback, method, formdata or {key:val}, placeholder
  c = new XMLHttpRequest;
  c.open(e||'get', a);
  c.onload = b;
  c.onerror = error;
  c.send(d||null)
}

function error(e){
  console.log('--Error--', this.type);
  console.log('this: ', this);
  console.log('Event: ', e)
}
function displayAjax(e){
  console.log(e, this);
}
x('WRONGURL', displayAjax);

ඉහත ස්ක්‍රිප්ටයේ, ඔබට දෝෂ හසුරුවන්නෙකු සිටින අතර එය සංඛ්‍යාත්මකව අර්ථ දක්වා ඇති අතර එමඟින් එය ක්‍රියාකාරීත්වයට බාධා නොකරයි. දෝෂ හසුරුවන්නා වෙනත් කාර්යයන් සඳහාද භාවිතා කළ හැකිය.

නමුත් ඇත්ත වශයෙන්ම දෝෂයක් ඇතිවීමට ඇති එකම ක්‍රමය වැරදි URL එකක් ලිවීමයි, එම අවස්ථාවේදී සෑම බ්‍රව්සරයක්ම දෝෂයක් විසි කරයි.

ඔබ අභිරුචි ශීර්ෂයන් සකසන්නේ නම්, ප්‍රතිචාර දැක්වීමේ ටයිප් එක අරා බෆරය හෝ වෙනත් දෙයක් සැකසීමට නම් දෝෂ හසුරුවන්නන් ප්‍රයෝජනවත් වේ ...

ඔබ 'POSTAPAPAP' ක්‍රමය ලෙස සමත් වුවද එය දෝෂයක් ඇති නොකරයි.

ඔබ 'fdggdgilfdghfldj' formdata ලෙස සමත් වුවද එය දෝෂයක් ඇති නොකරයි.

පළමු අවස්ථාවේ දී දෝෂය displayAjax()යටින් this.statusTextඇත Method not Allowed.

දෙවන අවස්ථාවේ දී, එය සරලව ක්රියා කරයි. ඔබ නිවැරදි පෝස්ට් දත්ත සමත් වූයේ නම් සේවාදායක පැත්තේ පරීක්ෂා කළ යුතුය.

හරස් වසමට ඉඩ නොදේ.

දෝෂ ප්‍රතිචාරයේදී දෝෂ කේත නොමැත.

this.typeදෝෂයට සකසා ඇත්තේ එය පමණි .

ඔබට දෝෂ පාලනය කිරීමට මුළුමනින්ම පාලනයක් නොමැති නම් දෝෂ හසුරුවන්නෙකු එකතු කරන්නේ ඇයි? ඇමතුම් ලබා ගැනීමේ කාර්යයේදී බොහෝ දෝෂ මේ තුළ නැවත ලබා දෙනු ලැබේ displayAjax().

එබැවින්: ඔබට URL නිසි ලෙස පිටපත් කර ඇලවිය හැකි නම් දෝෂ පරීක්‍ෂා කිරීම අවශ්‍ය නොවේ. ;)

PS: පළමු පරීක්ෂණය ලෙස මම x ('x', displayAjax) ලිව්වා ... එයට මුළුමනින්ම ප්‍රතිචාරයක් ලැබුණා ... ??? එබැවින් මම HTML පිහිටා ඇති ෆෝල්ඩරය පරීක්ෂා කළ අතර එහි 'x.xml' ගොනුවක් තිබුණි. එබැවින් ඔබේ ගොනුවේ දිගුව ඔබට අමතක වුව ද XMLHttpRequest 2 එය සොයා ගනීවි . මම කැමතියි


සමමුහුර්ත ගොනුවක් කියවන්න

එහෙම කරන්න එපා.

ඔබට ටික වේලාවක් බ්‍රව්සරය අවහිර කිරීමට අවශ්‍ය නම් ලස්සන විශාල .txtගොනුවක් සමමුහුර්ත කරන්න.

function omg(a, c){ // URL
  c = new XMLHttpRequest;
  c.open('GET', a, true);
  c.send();
  return c; // Or c.response
}

දැන් ඔබට කළ හැකිය

 var res = omg('thisIsGonnaBlockThePage.txt');

අසමමුහුර්ත ආකාරයකින් මෙය කිරීමට වෙනත් ක්‍රමයක් නොමැත. (ඔව්, setTimeout loop සමඟ ... නමුත් බැරෑරුම් ලෙස?)

තවත් කරුණක් නම් ... ඔබ ඒපීඅයි සමඟ වැඩ කරන්නේ නම් හෝ ඔබේම ලැයිස්තුවේ ලිපිගොනු හෝ ඔබ සෑම ඉල්ලීමක් සඳහාම විවිධ කාර්යයන් භාවිතා කරන්නේ නම් ...

ඔබ සෑම විටම එකම XML / JSON පූරණය කරන පිටුවක් තිබේ නම් හෝ ඔබට අවශ්‍ය වන්නේ එක් ශ්‍රිතයක් පමණි. එවැනි අවස්ථාවකදී, අජැක්ස් ශ්‍රිතය ටිකක් වෙනස් කර b වෙනුවට ඔබේ විශේෂ ශ්‍රිතය යොදන්න.


ඉහත කාර්යයන් මූලික භාවිතය සඳහා වේ.

ඔබට කාර්යය පුළුල් කිරීමට අවශ්‍ය නම් ...

ඔව් ඔබට පුළුවන්.

මම බොහෝ ඒපීඅයි භාවිතා කරන අතර සෑම HTML පිටුවකටම මම ඒකාබද්ධ කරන පළමු කාර්යයන්ගෙන් එකක් මෙම පිළිතුරේ පළමු අජැක්ස් ශ්‍රිතයයි, GET පමණි ...

නමුත් ඔබට XMLHttpRequest 2 සමඟ බොහෝ දේ කළ හැකිය:

මම බාගත කළමණාකරුවෙකු (නැවත ආරම්භ කිරීම, ගොනු කියවන්නා, ගොනු පද්ධතිය සමඟ දෙපස පරාසයන් භාවිතා කිරීම), කැන්වස් භාවිතා කරන විවිධ රූප ප්‍රතිරෝධක පරිවර්තකයන්, වෙබ් 64 දත්ත සමුදායන් පදනම් 64 රූප සමඟ ජනගහනය කිරීම සහ තවත් බොහෝ දේ කළෙමි ... නමුත් මෙම අවස්ථා වලදී ඔබ ශ්‍රිතයක් නිර්මාණය කළ යුත්තේ ඒ සඳහා පමණි අරමුණ ... සමහර විට ඔබට බ්ලොබ් එකක්, අරා බෆරයක් අවශ්‍යය, ඔබට ශීර්ෂයන් සැකසිය හැකිය, මයිමෙටයිප් අභිබවා යා හැකි අතර තවත් බොහෝ දේ ඇත ...

නමුත් මෙහි ඇති ප්‍රශ්නය වන්නේ අජැක්ස් ප්‍රතිචාරයක් ලබා දෙන්නේ කෙසේද යන්නයි ... (මම පහසු ක්‍රමයක් එක් කළෙමි.)


15
මෙම පිළිතුර ලස්සන (අපි හැමෝම වන අතර ආදරය JavaScript සමග XHR පළකිරීම සඳහා මෙම වැඩසටහන් සින්ටැක්ටික් සීනි - - XHR2 හා වෙබ් අඩවියේ ගොනුව දත්ත සහ multipart දත්ත මුළුමනින්ම නම් නියමයි) ඔබ බ්ලොග් මෙම පත් කිරීමට ඔබට අවශ්ය විය හැකිය (මම එය කැමතියි) හෝ පුස්තකාලයක පවා (නම ගැන විශ්වාස නැත x, ajaxහෝ xhrවඩා හොඳ විය හැකිය :)). AJAX ඇමතුමකින් ප්‍රතිචාර දැක්වීම සඳහා එය ආමන්ත්‍රණය කරන්නේ කෙසේදැයි මම නොදනිමි. (යමෙකුට තවමත් කළ හැකි var res = x("url")අතර එය ක්‍රියා නොකරන්නේ මන්දැයි තේරුම් ගත නොහැක;)). පැති සටහනක - ඔබ cක්‍රමයෙන් ආපසු ආවොත් එය සිසිල් වනු ඇත, එවිට පරිශීලකයින්ට errorයනාදිය සම්බන්ධ කර ගත හැකිය
බෙන්ජමින් ග ru න්බෝම්

25
2.ajax is meant to be async.. so NO var res=x('url')..මෙම ප්‍රශ්නයේ සහ පිළිතුරේ
මුලික

3
පළමු පේළියේ ඔබ එහි ඇති ඕනෑම වටිනාකමක් නැවත ලියන්නේ නම්, ශ්‍රිතවල 'c' පරාමිතියක් ඇත්තේ ඇයි? මට යමක් මග හැරී තිබේද?
බ්‍රයන් එච්.

2
"Var"
cocco

11
oc කොකෝ ඉතින් යතුරු එබීම් කිහිපයක් ඉතිරි කර ගැනීම සඳහා ඔබ SO පිළිතුරක නොමඟ යවන, කියවිය නොහැකි කේතයක් ලිව්වාද ? කරුණාකර එය නොකරන්න.
ගල්

316

ඔබ පොරොන්දු භාවිතා කරන්නේ නම්, මෙම පිළිතුර ඔබ වෙනුවෙන් වේ.

මෙයින් අදහස් කරන්නේ AngularJS, jQuery (විලම්බිත), ස්වදේශීය XHR ප්‍රතිස්ථාපනය (ලබා ගැනීම), EmberJS, BackboneJS හි සුරැකීම හෝ පොරොන්දු ලබා දෙන ඕනෑම නෝඩ් පුස්තකාලයක්.

ඔබේ කේතය මේ හා සමාන දෙයක් විය යුතුය:

function foo() {
    var data;
    // or $.get(...).then, or request(...).then, or query(...).then
    fetch("/echo/json").then(function(response){
        data = response.json();
    });
    return data;
}

var result = foo(); // result is always undefined no matter what.

ෆීලික්ස් ක්ලින්ග්, අජැක්ස් සඳහා ඇමතුම් සමඟ jQuery භාවිතා කරන පුද්ගලයින් සඳහා පිළිතුරක් ලිවීමට කදිම වැඩක් කළේය. ස්වදේශීය XHR සඳහා මට පිළිතුරක් ඇත. මෙම පිළිතුර ෆ්‍රොන්ටෙන්ඩ් හෝ බැකෙන්ඩ් වල පොරොන්දු සාමාන්‍යයෙන් භාවිතා කිරීම සඳහා ය.


මූලික ගැටළුව

බ්‍රවුසරයේ සහ NodeJS / io.js සහිත සේවාදායකයේ ඇති ජාවාස්ක්‍රිප්ට් සමගාමී ආකෘතිය අසමමුහුර්ත හා ප්‍රතික්‍රියාශීලී වේ.

පොරොන්දුවක් ලබා දෙන ක්‍රමයක් ඔබ අමතන සෑම විටම, thenහසුරුවන්නන් සෑම විටම අසමමුහුර්තව ක්‍රියාත්මක කරනු ලැබේ - එනම්, ඒවාට පහළින් ඇති කේතයෙන් පසුව එය .thenහසුරුවන්නෙකු තුළ නොමැත.

මෙයින් අදහස් කරන්නේ ඔබ විසින් නිර්වචනය කළ හසුරුව නැවත ලබා dataදෙන විට thenතවමත් ක්‍රියාත්මක වී නොමැති බවයි. මෙයින් අදහස් කරන්නේ ඔබ ආපසු එන අගය නියමිත වේලාවට නිවැරදි අගයට සකසා නොමැති බවයි.

මෙන්න නිකුතුව සඳහා සරල ප්‍රතිසමයක්:

    function getFive(){
        var data;
        setTimeout(function(){ // set a timer for one second in the future
           data = 5; // after a second, do this
        }, 1000);
        return data;
    }
    document.body.innerHTML = getFive(); // `undefined` here and not 5

වටිනාකම dataවේ undefinedසිට data = 5කොටසක් තවමත් ක්රියාවට නගා නැත. එය තත්පරයකින් ක්‍රියාත්මක වනු ඇති නමුත් ඒ වන විට එය ආපසු ලබා දුන් වටිනාකමට අදාළ නොවේ.

මෙහෙයුම තවම සිදු නොවූ හෙයින් (AJAX, සේවාදායක ඇමතුම, IO, ටයිමර්) ඉල්ලීමට පෙර එම අගය කුමක්දැයි ඔබේ කේතයට පැවසීමට අවස්ථාව ලැබීමට පෙර ඔබ එම අගය නැවත ලබා දෙයි.

මෙම ගැටළුවට ඇති විය හැකි එක් විසඳුමක් වන්නේ නැවත ක්‍රියාශීලීව කේත කිරීම, ගණනය කිරීම අවසන් වූ විට කළ යුතු දේ ඔබේ වැඩසටහනට පැවසීමයි. ස්වභාවධර්මයේ තාවකාලික (කාල සංවේදී) වීමෙන් මෙය සක්‍රියව සක්‍රීය කරයි.

පොරොන්දු ඉක්මණින් නැවත ලබා ගැනීම

පොරොන්දුවක් යනු කාලයත් සමඟ ඇති වටිනාකමකි . පොරොන්දු වලට රාජ්‍යයක් ඇත, ඒවා ආරම්භ වන්නේ කිසිදු වටිනාකමක් නොමැතිව වන අතර ඒවා සමථයකට පත් කළ හැකිය:

  • ඉටු හැටිත් සාර්ථකව නිම තේරුම.
  • ප්‍රතික්ෂේප කිරීම යනු ගණනය කිරීම අසාර්ථක වූ බවයි.

පොරොන්දුවක් මගින් රාජ්‍යයන් වෙනස් කළ හැක්කේ එක් වරක් පමණක් වන අතර එය සෑම විටම එකම තත්වයේ සදහටම පවතිනු ඇත. ඔබට thenහසුරුවන්නන්ගේ වටිනාකම උකහා ගැනීමට සහ දෝෂ හැසිරවීමට පොරොන්දු වලට ඇමිණිය හැකිය. thenහසුරුවන්නන් ඇමතුම් දම්වැල් දැමීමට ඉඩ දෙයි . පොරොන්දු නිර්මාණය කරනු ලබන්නේ ඒවා ආපසු ලබා දෙන API භාවිතා කිරීමෙනි . උදාහරණයක් ලෙස, වඩාත් නවීන AJAX ප්‍රතිස්ථාපනය fetchහෝ jQuery $.getනැවත පැමිණීමේ පොරොන්දු.

අපි .thenපොරොන්දුවක් ඉල්ලා සිට එයින් යමක් ආපසු ලබා දෙන විට - සැකසූ වටිනාකම සඳහා අපට පොරොන්දුවක් ලැබේ . අපි වෙනත් පොරොන්දුවක් ආපසු ලබා දුන්නොත් අපට පුදුමාකාර දේවල් ලැබෙනු ඇත, නමුත් අපි අපේ අශ්වයන් අල්ලා ගනිමු.

පොරොන්දු සමඟ

ඉහත ගැටලුව පොරොන්දු සමඟ විසඳා ගන්නේ කෙසේදැයි බලමු. පළමුවෙන්ම, ප්‍රමාද ශ්‍රිතයක් නිර්මාණය කිරීම සඳහා පොරොන්දු ඉදිකිරීම්කරු භාවිතා කරමින් ඉහළින් පොරොන්දු තත්වයන් පිළිබඳ අපගේ අවබෝධය පෙන්වමු :

function delay(ms){ // takes amount of milliseconds
    // returns a new promise
    return new Promise(function(resolve, reject){
        setTimeout(function(){ // when the time is up
            resolve(); // change the promise to the fulfilled state
        }, ms);
    });
}

දැන්, අපි පොරොන්දු භාවිතා කිරීම සඳහා setTimeout පරිවර්තනය කිරීමෙන් පසුව, thenඑය ගණන් කිරීමට අපට භාවිතා කළ හැකිය :

function delay(ms){ // takes amount of milliseconds
  // returns a new promise
  return new Promise(function(resolve, reject){
    setTimeout(function(){ // when the time is up
      resolve(); // change the promise to the fulfilled state
    }, ms);
  });
}

function getFive(){
  // we're RETURNING the promise, remember, a promise is a wrapper over our value
  return delay(100).then(function(){ // when the promise is ready
      return 5; // return the value 5, promises are all about return values
  })
}
// we _have_ to wrap it like this in the call site, we can't access the plain value
getFive().then(function(five){ 
   document.body.innerHTML = five;
});

මූලික වශයෙන්, ඒ වෙනුවට ආපසු අගය නිසා සමගාමී ආකෘතිය අපි නොහැකි - අපි එය නැවත කරන්නේ දවටනය අපි හැකි බව අගය සඳහා unwrap සමග then. එය ඔබට විවෘත කළ හැකි පෙට්ටියක් වැනිය then.

මෙය යෙදීම

ඔබගේ මුල් API ඇමතුම සඳහා මෙය සමාන වේ, ඔබට:

function foo() {
    // RETURN the promise
    return fetch("/echo/json").then(function(response){
        return response.json(); // process it inside the `then`
    });
}

foo().then(function(response){
    // access the value inside the `then`
})

එබැවින් මෙයද ක්‍රියාත්මක වේ. දැනටමත් අසමමුහුර්ත ඇමතුම් වලින් අපට අගයන් ආපසු ලබා දිය නොහැකි බව අපි ඉගෙන ගෙන ඇති නමුත් අපට පොරොන්දු භාවිතා කර ඒවා සැකසීමට හැකිය. අසමමුහුර්ත ඇමතුමකින් ප්‍රතිචාරය ලබා දෙන්නේ කෙසේදැයි අපි දැන් දනිමු.

ES2015 (ES6)

ඊඑස් 6 විසින් ජනක යන්ත්‍ර හඳුන්වා දෙන අතර ඒවා මැදට පැමිණ නැවත ඒවා නැවත ආරම්භ කළ හැකිය. මෙය සාමාන්‍යයෙන් අනුක්‍රම සඳහා ප්‍රයෝජනවත් වේ, උදාහරණයක් ලෙස:

function* foo(){ // notice the star, this is ES6 so new browsers/node/io only
    yield 1;
    yield 2;
    while(true) yield 3;
}

පුනරාවර්තනය කළ හැකි අනුක්‍රමය හරහා අනුකාරකයක් ලබා දෙන ශ්‍රිතයකි 1,2,3,3,3,3,..... මෙය තනිවම සිත්ගන්නාසුළු වන අතර බොහෝ අවස්ථාවන් සඳහා ඉඩක් විවෘත කරයි.

අප නිපදවන අනුක්‍රමය සංඛ්‍යා වලට වඩා ක්‍රියා අනුක්‍රමයක් නම් - යම් ක්‍රියාවක් සිදු වූ සෑම අවස්ථාවකම අපට එය විරාමයක් තබා ශ්‍රිතය නැවත ආරම්භ කිරීමට පෙර බලා සිටින්න. එබැවින් සංඛ්‍යා අනුක්‍රමයක් වෙනුවට අපට අවශ්‍ය වන්නේ අනාගත අගයන්ගේ අනුක්‍රමයකි - එනම්: පොරොන්දු.

මෙය තරමක් උපක්‍රමශීලී නමුත් ඉතා ප්‍රබල උපක්‍රමයක් මඟින් සමමුහුර්ත ආකාරයකින් අසමමුහුර්ත කේතය ලිවීමට අපට ඉඩ සලසයි. ඔබ වෙනුවෙන් මෙය කරන "ධාවකයන්" කිහිප දෙනෙක් සිටිති, එකක් ලිවීම කෙටි කේත පේළි කිහිපයක් වන නමුත් මෙම පිළිතුරේ සීමාවෙන් ඔබ්බට ය. මම Promise.coroutineමෙහි බ්ලූබර්ඩ් භාවිතා කරමි , නමුත් වෙනත් එතීම් coහෝ Q.asyncතිබේ.

var foo = coroutine(function*(){
    var data = yield fetch("/echo/json"); // notice the yield
    // code here only executes _after_ the request is done
    return data.json(); // data is defined
});

මෙම ක්‍රමය මඟින් පොරොන්දුවක්ම ලබා දෙයි, එය අපට වෙනත් කොරොටින් වලින් පරිභෝජනය කළ හැකිය. උදාහරණයක් වශයෙන්:

var main = coroutine(function*(){
   var bar = yield foo(); // wait our earlier coroutine, it returns a promise
   // server call done here, code below executes when done
   var baz = yield fetch("/api/users/"+bar.userid); // depends on foo's result
   console.log(baz); // runs after both requests done
});
main();

ES2016 (ES7)

ES7 හි, මෙය තවදුරටත් ප්‍රමිතිගත කර ඇත, මේ වන විට යෝජනා කිහිපයක් ඇත, නමුත් ඒ සියල්ලෙහිම ඔබට awaitපොරොන්දු විය හැකිය . ඉහත asyncසහ ඊඑස් 6 යෝජනාව සඳහා මෙය “සීනි” (වඩා හොඳ සින්ටැක්ස්) පමණි await. ඉහත උදාහරණය කිරීම:

async function foo(){
    var data = await fetch("/echo/json"); // notice the await
    // code here only executes _after_ the request is done
    return data.json(); // data is defined
}

එය තවමත් පොරොන්දුවක් ලබා දෙයි.


මෙය පිළිගත් පිළිතුර විය යුතුය. +1 අසයික් / බලා සිටීම සඳහා (අප එසේ නොවිය යුතුද return await data.json();?)
ලුවිස් ඩොනොවන්

247

ඔබ අජැක්ස් වැරදි ලෙස භාවිතා කරයි. අදහස වන්නේ එය කිසිවක් ආපසු ලබා දීම නොව, ඒ වෙනුවට දත්ත හසුරුවන ඇමතුම් ආපසු ගැනීමේ ශ්‍රිතයක් වෙත ලබා දීමයි.

එනම්:

function handleData( responseData ) {

    // Do what you want with the data
    console.log(responseData);
}

$.ajax({
    url: "hi.php",
    ...
    success: function ( data, status, XHR ) {
        handleData(data);
    }
});

ඉදිරිපත් කරන්නා තුළ කිසිවක් ආපසු ලබා දීමෙන් කිසිවක් සිදු නොවේ. ඔබ ඒ වෙනුවට දත්ත භාර දිය යුතුය, නැතහොත් සාර්ථක ශ්‍රිතය තුළ ඔබට අවශ්‍ය දේ කෙලින්ම කළ යුතුය.


13
මෙම පිළිතුර සම්පුර්ණයෙන්ම අර්ථාන්විත ය ... ඔබේ සාර්ථකත්ව ක්‍රමය ඇමතුමක් තුළ ඇති ඇමතුමක් පමණි. ඔබට තිබිය හැකි success: handleDataඅතර එය ක්‍රියාත්මක වනු ඇත.
ජැක් ジ ャ ッ ク

5
"හැන්ඩ්ල් ඩේටා" ට පිටතින් "ප්‍රතිචාර දත්ත" ආපසු ලබා දීමට ඔබට අවශ්‍ය නම් කුමක් කළ යුතුද ... :) ... ඔබ එය කරන්නේ කෙසේද ...? ... සරල ප්‍රතිලාභයක් නිසා එය අජැක්ස් හි "සාර්ථක" ඇමතුම වෙත නැවත ලැබෙනු ඇත ... සහ "හැන්ඩ්ල් ඩේටා" ට පිටතින් නොවේ ...
pesho hristov

Ac ජැක් සහ @ පෙෂෝ hristov ඔබට මෙම කරුණ මඟ හැරුණි. ඉදිරිපත් කරන්න හසුරුවන්නා ක්‍රමය නොවේ success, එය අවට විෂය පථයයි $.ajax.
travnik

@travnik මට ඒක මග හැරුනේ නැහැ. ඔබ හැන්ඩ් ඩේටා හි අන්තර්ගතය ගෙන එය සාර්ථක ක්‍රමයට දැමුවහොත් එය හරියටම ක්‍රියාත්මක වේ ...
ජැක් ジ ャ ッ ク

234

සරලම විසඳුම වන්නේ ජාවාස්ක්‍රිප්ට් ශ්‍රිතයක් නිර්මාණය කර එය අජැක්ස් ඇමතුම සඳහා අමතන්න success.

function callServerAsync(){
    $.ajax({
        url: '...',
        success: function(response) {

            successCallback(response);
        }
    });
}

function successCallback(responseObj){
    // Do something like read the response and show data
    alert(JSON.stringify(responseObj)); // Only applicable to JSON response
}

function foo(callback) {

    $.ajax({
        url: '...',
        success: function(response) {
           return callback(null, response);
        }
    });
}

var result = foo(function(err, result){
          if (!err)
           console.log(result);    
}); 

3
එය negative ණාත්මක ලෙස ඡන්දය දුන්නේ කවුදැයි මම නොදනිමි. නමුත් මෙය අවට වැඩක් වන අතර ඇත්ත වශයෙන්ම මම මෙම යෙදුම සමස්ත යෙදුමක් නිර්මාණය කිරීමට භාවිතා කළෙමි. Jquery.ajax දත්ත නැවත ලබා නොදෙන බැවින් ඉහත ප්‍රවේශය භාවිතා කිරීම වඩා හොඳය. එය වැරදියි නම් කරුණාකර එය කිරීමට වඩා හොඳ ක්‍රමයක් පැහැදිලි කර යෝජනා කරන්න.
හේමන්ත් බැව්ල්

11
කණගාටුයි, මට අදහස් දැක්වීමට අමතක විය (මම සාමාන්‍යයෙන් එසේ කරමි!). මම එය පහත් කළා. ඩවුන්වොට්ස් මගින් සත්‍ය කරුණු හෝ lack නතාවයන් දක්වන්නේ නැත, ඒවා සන්දර්භය තුළ ප්‍රයෝජනවත් බව හෝ lack නතාව පෙන්නුම් කරයි. මේ වන විටත් එය වඩාත් විස්තරාත්මකව පැහැදිලි කර ඇති ෆීලික්ස්ගේ පිළිතුරෙන් මට ඔබේ පිළිතුර ප්‍රයෝජනවත් නොවේ. පැති සටහනක, JSON නම් ඔබ ප්‍රතිචාරය දැඩි කරන්නේ ඇයි?
බෙන්ජමින් ග ru න්බෝම්

5
හරි .. en බෙන්ජමින් මම JSON වස්තුවක් නූල් බවට පරිවර්තනය කිරීම සඳහා stringify භාවිතා කළෙමි. ඔබේ අදහස පැහැදිලි කිරීම ගැන ස්තූතියි. වඩාත් සවිස්තරාත්මක පිළිතුරු පළ කිරීමට මතක තබා ගනී.
හේමන්ත් බැව්ල්

"සාර්ථක කැල්බැක්" ට පිටතින් "ප්‍රතිචාර ඕබ්" ආපසු ලබා දීමට ඔබට අවශ්‍ය නම් කුමක් කළ යුතුද ... :) ... ඔබ එය කරන්නේ කෙසේද ...? ... සරල ප්‍රතිලාභයක් නිසා එය අජැක්ස් හි "සාර්ථක" ඇමතුම වෙත නැවත ලැබෙනු ඇත ... සහ "සාර්ථක කැල්බැක්" ට පිටතින් නොවේ ...
pesho hristov

221

මම බිහිසුණු පෙනුමක් ඇති, අතින් ඇදගත් විකට චිත්‍රයකින් පිළිතුරු දෙන්නෙමි. දෙවන රූපය හේතුව ද මෙය resultවේ undefinedඔබගේ කේතය උදාහරණය.

රූප විස්තරය මෙහි ඇතුළත් කරන්න


32
පින්තූරයක් වචන දහසක් වටිනවා , පුද්ගලයා A - ඔහුගේ මෝටර් රථය සවි කිරීමට B විස්තර විමසන්න, අනෙක් අතට පුද්ගලයා B - අජැක්ස් ඇමතුමක් ලබා දී කාර් සවි කිරීමේ විස්තර සඳහා සේවාදායකයාගෙන් ප්‍රතිචාරයක් බලාපොරොත්තුවෙන් සිටී, ප්‍රතිචාරය ලැබුණු විට, අජැක්ස් සාර්ථක ශ්‍රිතය පුද්ගලයා අමතයි B ක්‍රියාකාරීත්වය සහ ප්‍රතිචාරය එයට තර්කයක් ලෙස සම්මත කරයි, A පුද්ගලයාට පිළිතුර ලැබේ.
shaijut

10
සංකල්ප නිරූපණය කිරීම සඳහා ඔබ එක් එක් රූපය සමඟ කේත රේඛා එකතු කළහොත් එය ඉතා හොඳ වේ.
හසන් බේග්

1
මේ අතර, මෝටර් රථය සමඟ සිටි පුද්ගලයා පාර දෙපස සිරවී සිටී. ඉදිරියට යාමට පෙර මෝටර් රථය සවි කිරීමට ඔහුට අවශ්‍යය . ඔහු දැන් තනිවම පාර දෙපස බලා සිටී ... තත්වය වෙනස්වීම් බලාපොරොත්තුවෙන් ඔහු දුරකථනයෙන් සිටිනු ඇත, නමුත් කාර්මිකයා එය නොකරනු ඇත ... කාර්මිකයා පැවසුවේ තම රැකියාව සමඟ ඉදිරියට යා යුතු බවත් නොහැකි බවත් හුදෙක් දුරකථනයේ රැඳී සිටින්න. ඔහුට හැකි ඉක්මනින් ඔහුව නැවත කැඳවන බවට කාර්මිකයා පොරොන්දු විය. පැය 4 කට පමණ පසු, පුද්ගලයා අතහැර දමා ber බර්ට කතා කරයි. - කල් ඉකුත් වීමේ උදාහරණය.
බැරිපිකර්

ry බාර්රිපිකර් :- ඩී දීප්තිමත්!
ජොහැන්නස් ෆැරන්ක්රුග්

159

කෝණික 1

AngularJS භාවිතා කරන පුද්ගලයින් සඳහා , මෙම තත්වය භාවිතයෙන් හැසිරවිය හැකිය Promises.

මෙන්න එය පවසයි,

අසමමුහුර්ත ශ්‍රිත ඉවත් කිරීමට පොරොන්දු භාවිතා කළ හැකි අතර එක් කෙනෙකුට බහුවිධ කාර්යයන් එකට සම්බන්ධ කිරීමට ඉඩ දෙයි.

ඔබට මෙහි හොඳ පැහැදිලි කිරීමක් ද සොයාගත හැකිය .

පහත සඳහන් ලියකියවිලි වල උදාහරණය .

  promiseB = promiseA.then(
    function onSuccess(result) {
      return result + 1;
    }
    ,function onError(err) {
      //Handle error
    }
  );

 // promiseB will be resolved immediately after promiseA is resolved 
 // and its value will be the result of promiseA incremented by 1.

කෝණික 2 සහ පසුව

දී Angular2පහත සඳහන් උදාහරණය සලකා බලන සමග, නමුත් එහි නිර්දේශ භාවිතා කිරීමට Observablesසමග Angular2.

 search(term: string) {
     return this.http
  .get(`https://api.spotify.com/v1/search?q=${term}&type=artist`)
  .map((response) => response.json())
  .toPromise();

}

ඔබට එය මේ ආකාරයෙන් පරිභෝජනය කළ හැකිය,

search() {
    this.searchService.search(this.searchField.value)
      .then((result) => {
    this.result = result.artists.items;
  })
  .catch((error) => console.error(error));
}

බලන්න මුල් මෙතන පශ්චාත්. නමුත් ටයිප්ස්ක්‍රිප්ට් ස්වදේශික එස් 6 පොරොන්දු සඳහා සහය නොදක්වයි , ඔබට එය භාවිතා කිරීමට අවශ්‍ය නම්, ඒ සඳහා ඔබට ප්ලගිනය අවශ්‍ය විය හැකිය.

මීට අමතරව මෙහි පොරොන්දු පිරිවිතරයන් අර්ථ දක්වා ඇත.


15
පොරොන්දු කෙසේ වෙතත් මෙම ගැටළුව විසඳන්නේ කෙසේද යන්න මෙයින් පැහැදිලි නොවේ.
බෙන්ජමින් ග ru න්බෝම්

4
jQuery සහ බෝගයන්ගේ ක්රම මෙන්ම නැවත පොරොන්දු දෙකම. ඔබේ පිළිතුර සංශෝධනය කිරීමට මම යෝජනා කරමි. JQuery එක සමාන නොවුනත් (එහෙනම් තියෙනවා, නමුත් අල්ලා ගැනීම එසේ නොවේ).
ට්රැකර් 1

153

මෙහි ඇති බොහෝ පිළිතුරු ඔබට තනි අසමමුහුර්ත මෙහෙයුමක් ඇති විට ප්‍රයෝජනවත් යෝජනා ලබා දෙයි, නමුත් සමහර විට, අරාවෙහි හෝ වෙනත් ලැයිස්තු වැනි ව්‍යුහයක සෑම ප්‍රවේශයක් සඳහාම අසමමුහුර්ත මෙහෙයුමක් කිරීමට අවශ්‍ය වූ විට මෙය පැමිණේ . පෙළඹවීම මෙය කිරීමට ය:

// WRONG
var results = [];
theArray.forEach(function(entry) {
    doSomethingAsync(entry, function(result) {
        results.push(result);
    });
});
console.log(results); // E.g., using them, returning them, etc.

උදාහරණයක්:

ක්‍රියා නොකිරීමට හේතුව, ඔබ ප්‍රති .ල doSomethingAsyncභාවිතා කිරීමට උත්සාහ කරන කාලය වන විට ලැබෙන ඇමතුම් තවමත් ක්‍රියාත්මක නොවීමයි.

එබැවින්, ඔබට අරාවක් තිබේ නම් (හෝ යම් ආකාරයක ලැයිස්තුවක්) සහ එක් එක් ප්‍රවේශය සඳහා අසමමුහුර්ත මෙහෙයුම් කිරීමට අවශ්‍ය නම්, ඔබට විකල්ප දෙකක් තිබේ: මෙහෙයුම් සමාන්තරව (අතිච්ඡාදනය) හෝ ශ්‍රේණියේ (අනුපිළිවෙලින් එකින් එක) කරන්න.

සමාන්තරයි

ඔබට ඒවා සියල්ලම ආරම්භ කර ඔබ කොපමණ ඇමතුම් ලබා ගත යුතුදැයි සොයා බැලිය හැකිය, පසුව ඔබට බොහෝ ඇමතුම් ලබා ගත් පසු ප්‍රති results ල භාවිතා කරන්න:

var results = [];
var expecting = theArray.length;
theArray.forEach(function(entry, index) {
    doSomethingAsync(entry, function(result) {
        results[index] = result;
        if (--expecting === 0) {
            // Done!
            console.log("Results:", results); // E.g., using the results
        }
    });
});

උදාහරණයක්:

(අපට එය ඉවත් කර expectingහුදෙක් භාවිතා කළ හැකිය results.length === theArray.length, නමුත් එමඟින් අපට එම හැකියාව විවෘත වේtheArray ඇමතුම් කැපී පෙනෙන අතර වෙනස් විය හැකි එය ...)

අපි භාවිතා කරන ආකාරය දැනුම් indexසිට forEachඇති ප්රතිඵලය බේරා ගැනීමට results(අසමකාලීක ඇමතුම් ඒවා ආරම්භ කරන පිණිස අවශ්යයෙන්ම සම්පූර්ණ නැහැ සිට) ප්රතිඵල සඳහා පිටතට පැමිණීමට පවා නම්, එය සම්බන්ධ වන පිවිසුම් ලෙස ද එම තනතුර ය.

එහෙත්, ඔබ කළ යුතු දේ නම්, නැවත උත්සවයකට සිට එම ප්රතිඵල ඇති විය හැකිද? අනෙක් පිළිතුරු පෙන්වා දී ඇති පරිදි, ඔබට බැහැ; ඔබේ කාර්යය පිළිගෙන ඇමතුමක් ලබා ගත යුතුය (නැතහොත් පොරොන්දුවක් ආපසු එවන්න ). මෙන්න ඇමතුම් ආපසු අනුවාදය:

function doSomethingWith(theArray, callback) {
    var results = [];
    var expecting = theArray.length;
    theArray.forEach(function(entry, index) {
        doSomethingAsync(entry, function(result) {
            results[index] = result;
            if (--expecting === 0) {
                // Done!
                callback(results);
            }
        });
    });
}
doSomethingWith(theArray, function(results) {
    console.log("Results:", results);
});

උදාහරණයක්:

නැතහොත් මෙන්න Promiseඒ වෙනුවට නැවත එන අනුවාදයක් :

function doSomethingWith(theArray) {
    return new Promise(function(resolve) {
        var results = [];
        var expecting = theArray.length;
        theArray.forEach(function(entry, index) {
            doSomethingAsync(entry, function(result) {
                results[index] = result;
                if (--expecting === 0) {
                    // Done!
                    resolve(results);
                }
            });
        });
    });
}
doSomethingWith(theArray).then(function(results) {
    console.log("Results:", results);
});

ඇත්ත වශයෙන්ම, doSomethingAsyncඅපට දෝෂයන් සම්මත වුවහොත් , අපි භාවිතා කරමුreject ඇති වූ විට පොරොන්දුව ප්‍රතික්ෂේප කිරීමට කරමු.)

උදාහරණයක්:

(නැතහොත් විකල්පයක් ලෙස, ඔබට doSomethingAsyncපොරොන්දුවක් ලබා දීම සඳහා එතීම කළ හැකිය , ඉන්පසු පහත දේ කරන්න ...)

doSomethingAsyncඔබට පොරොන්දුවක් ලබා දෙන්නේ නම් , ඔබට මෙය භාවිතා කළ හැකිය Promise.all:

function doSomethingWith(theArray) {
    return Promise.all(theArray.map(function(entry) {
        return doSomethingAsync(entry);
    }));
}
doSomethingWith(theArray).then(function(results) {
    console.log("Results:", results);
});

doSomethingAsyncදෙවන හා තෙවන තර්කය නොසලකා හරින බව ඔබ දන්නේ නම් , ඔබට එය කෙලින්ම යැවිය හැකිය map( mapතර්ක තුනකින් එහි ඇමතුම අමතන්න , නමුත් බොහෝ අය භාවිතා කරන්නේ පළමු වරට පමණි):

function doSomethingWith(theArray) {
    return Promise.all(theArray.map(doSomethingAsync));
}
doSomethingWith(theArray).then(function(results) {
    console.log("Results:", results);
});

උදාහරණයක්:

Promise.allඔබ දුන් පොරොන්දු සියල්ල විසඳූ විට එහි ප්‍රති results ල සමූහයක් සමඟ එහි පොරොන්දුව විසඳන බව සලකන්න , නැතහොත් පළමු වරට දුන් පොරොන්දුව ප්‍රතික්ෂේප කරයි. ඔබ දුන් ප්‍රතික්ෂේප කරයි.

මාලාවක්

මෙහෙයුම් සමාන්තරව පැවතීමට ඔබට අවශ්‍ය නැතැයි සිතමු? ඔබට ඒවා එකින් එක ක්‍රියාත්මක කිරීමට අවශ්‍ය නම්, ඊළඟ මෙහෙයුම ආරම්භ කිරීමට පෙර එක් එක් මෙහෙයුම අවසන් වන තෙක් ඔබ බලා සිටිය යුතුය. මෙන්න එය කරන ශ්‍රිතයක උදාහරණයක් වන අතර ප්‍රති result ලය සමඟ ඇමතුමක් ලබා ගත හැකිය:

function doSomethingWith(theArray, callback) {
    var results = [];
    doOne(0);
    function doOne(index) {
        if (index < theArray.length) {
            doSomethingAsync(theArray[index], function(result) {
                results.push(result);
                doOne(index + 1);
            });
        } else {
            // Done!
            callback(results);
        }
    }
}
doSomethingWith(theArray, function(results) {
    console.log("Results:", results);
});

(අප මාලාවේ වැඩ කරන්නේ නිසා, අපි භාවිතා කළ හැකිය results.push(result)අපි පිණිස පිටතට ප්රතිඵල ලබා ගත නොහැකි වේ දන්නේ සිට. ඉහත අප භාවිත කළ හැකිව තිබුණි දී results[index] = result;, නමුත් පහත සඳහන් උදාහරණ කිහිපයක් අපි දර්ශකය නැහැ භාවිතා කිරීමට.)

උදාහරණයක්:

(නැතහොත්, නැවතත්, ඒ සඳහා ආවරණයක් සාදන්න, doSomethingAsyncඔබට පොරොන්දුවක් ලබා දී පහත දේ කරන්න ...)

නම් doSomethingAsyncඔබ පොරොන්දුව ලබා දෙයි, ඔබ ES2017 + කාරක රීති (සමහර විට වැනි transpiler සමග භාවිතා කළ හැකි නම් බාබෙල් ), ඔබ භාවිතා කළ හැකිය asyncඋත්සවය සමඟ for-ofහා await:

async function doSomethingWith(theArray) {
    const results = [];
    for (const entry of theArray) {
        results.push(await doSomethingAsync(entry));
    }
    return results;
}
doSomethingWith(theArray).then(results => {
    console.log("Results:", results);
});

උදාහරණයක්:

ඔබට ES2017 + සින්ටැක්ස් (තවමත්) භාවිතා කළ නොහැකි නම්, ඔබට “පොරොන්දුව අඩු කරන්න” රටාවෙහි විචල්‍යතාවයක් භාවිතා කළ හැකිය (මෙය සාමාන්‍ය පොරොන්දුව අඩු කිරීමට වඩා සංකීර්ණ ය, මන්ද අපි ප්‍රති one ලය එකකින් ඊළඟට නොයවන නමුත් ඒ වෙනුවට ඔවුන්ගේ ප්‍රති results ල පෙළට එකතු කිරීම):

function doSomethingWith(theArray) {
    return theArray.reduce(function(p, entry) {
        return p.then(function(results) {
            return doSomethingAsync(entry).then(function(result) {
                results.push(result);
                return results;
            });
        });
    }, Promise.resolve([]));
}
doSomethingWith(theArray).then(function(results) {
    console.log("Results:", results);
});

උදාහරණයක්:

... එය ES2015 + ඊතල ශ්‍රිත සමඟ අඩු කරදරකාරී වේ :

function doSomethingWith(theArray) {
    return theArray.reduce((p, entry) => p.then(results => doSomethingAsync(entry).then(result => {
        results.push(result);
        return results;
    })), Promise.resolve([]));
}
doSomethingWith(theArray).then(results => {
    console.log("Results:", results);
});

උදාහරණයක්:


1
if (--expecting === 0)කරුණාකර කේතයේ කොටස ක්‍රියා කරන ආකාරය ඔබට පැහැදිලි කළ හැකිද ? ඔබගේ විසඳුමේ ඇමතුම් ලබා ගැනීමේ අනුවාදය මා වෙනුවෙන් විශාල ලෙස ක්‍රියා කරයි, එම ප්‍රකාශය සමඟ ඔබ සම්පූර්ණ කළ ප්‍රතිචාර ගණන පරීක්ෂා කරන්නේ කෙසේදැයි මට තේරෙන්නේ නැත. එය මගේ පැත්තෙන් දැනුමක් නොමැතිකම අගය කරන්න. චෙක්පත ලිවිය හැකි විකල්ප ක්‍රමයක් තිබේද?
සාරා

Ara සාරා: expectingආරම්භ වන්නේ එහි වටිනාකමෙනි array.length, එය අප ඉල්ලීම් කීයක් කරන්නද යන්නයි. එම ඉල්ලීම් සියල්ලම ආරම්භ වන තුරු ඇමතුම ලබා නොදෙන බව අපි දනිමු. ඇමතුම් ලබා ගැනීමේදී if (--expecting === 0)මෙය සිදු කරයි: 1. අඩු කිරීම් expecting(අපට ප්‍රතිචාරයක් ලැබී ඇත, එබැවින් අපි අඩු ප්‍රතිචාරයක් අපේක්ෂා කරමු) සහ අඩුවීමෙන් පසු අගය 0 නම් (අපි තවත් ප්‍රතිචාර බලාපොරොත්තු නොවෙමු), අපි ඉවරයි!
ටී. ජේ. ක්‍රෝඩර්

1
At පැට්‍රික් රොබට්ස් - ස්තූතියි !! ඔව්, පිටපත් කිරීමේ හා අලවන දෝෂය, එම උදාහරණයේ දී දෙවන තර්කය මුළුමනින්ම නොසලකා හරින ලදි (ඔබ පෙන්වා දුන් පරිදි resultsඑය නොපවතින බැවින් එය අසාර්ථක නොවූ එකම හේතුව එයයි ). :-) එය නිවැරදි කළා.
ටී.ජේ ක්‍රෝඩර්

111

මෙම උදාහරණය දෙස බලන්න:

var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope,$http) {

    var getJoke = function(){
        return $http.get('http://api.icndb.com/jokes/random').then(function(res){
            return res.data.value;  
        });
    }

    getJoke().then(function(res) {
        console.log(res.joke);
    });
});

ඔබ දැක ගැනීමට හැකි වන පරිදි getJokeවේ නැවත හැරී විසඳා පොරොන්දුව (එය නැවත විට නිරාකරණය res.data.value). එබැවින් $ http.get ඉල්ලීම සම්පුර්ණ වන තෙක් ඔබ බලා සිට පසුව console.log (res.joke) ක්‍රියාත්මක කරනු ලැබේ (සාමාන්‍ය අසමමුහුර්ත ප්‍රවාහයක් ලෙස).

මෙය plnkr:

http://embed.plnkr.co/XlNR7HpCaIhJxskMJfSg/

ES6 මාර්ගය (අසින්ක් - බලා සිටින්න)

(function(){
  async function getJoke(){
    let response = await fetch('http://api.icndb.com/jokes/random');
    let data = await response.json();
    return data.value;
  }

  getJoke().then((joke) => {
    console.log(joke);
  });
})();

107

දත්ත බන්ධනය හෝ ගබඩා සංකල්පය යන ක්‍රම දෙකෙන් එකකි මෙය නව JavaScript රාමුව බොහෝ භාවිතා කරන බව ද ඔබ වෙනුවෙන් විශාල වැඩ කරනු ඇත ...

එබැවින් ඔබ දත්ත බන්ධන හෝ ගබඩා සංකල්ප දෙකක් කරන කෝණික, ප්‍රතික්‍රියා හෝ වෙනත් රාමු භාවිතා කරන්නේ නම් මෙම ගැටළුව ඔබ වෙනුවෙන්ම නිරාකරණය කර ඇත, එබැවින් පහසු වචන වලින් කිවහොත් ඔබේ ප්‍රති result ලය පළමු අදියරේදී ඔබට ලැබී ඇතundefinedresult = undefined ඔබට ලැබෙනු ඇත. දත්ත, එවිට ඔබට ප්‍රති result ලය ලැබුණු විගසම එය යාවත්කාලීන වන අතර ඔබේ අජැක්ස් ඇමතුමේ ප්‍රතිචාරය නව අගයට පවරනු ලැබේ ...

නමුත් ඔබට එය පිරිසිදු javascript හෝ jQuery වලින් කළ හැක්කේ කෙසේද මෙම ප්‍රශ්නයේදී ඔබ ඇසූ පරිදි කෙසේද?

ඔබ වෙනුවෙන් එය හැසිරවීමට ඔබට ඇමතුමක් , පොරොන්දුවක් සහ මෑතකදී නිරීක්ෂණය කළ හැකිය, උදාහරණයක් ලෙස අපට යම් කාර්යයක් තිබේ නම් success()හෝ then()ඔබේ දත්ත ඔබ වෙනුවෙන් සූදානම් වූ විට ක්‍රියාත්මක වනු ඇත, ඇමතුම් ලබා ගැනීම හෝ නිරීක්ෂණය කළ හැකි දායකත්වය ලබා ගැනීම .

උදාහරණයක් ලෙස ඔබ jQuery භාවිතා කරන නඩුවේදී , ඔබට මේ වගේ දෙයක් කළ හැකිය:

$(document).ready(function(){
    function foo() {
        $.ajax({url: "api/data", success: function(data){
            fooDone(data); //after we have data, we pass it to fooDone
        }});
    };

    function fooDone(data) {
        console.log(data); //fooDone has the data and console.log it
    };

    foo(); //call happens here
});

මෙම අසමමුහුර්ත දේවල් කිරීමට නව ක්‍රම වන පොරොන්දු සහ නිරීක්ෂණ පිළිබඳ වැඩි විස්තර සඳහා .


මෙම ගෝලීය විෂය පථය දී නම් හොඳයි, ඒත් සමහර විට ඔබ මෙම callback උදා කිරීම සඳහා සුදුසු සන්දර්භය සහතික කිරීම සඳහා අවශ්ය සමහර මොඩියුලය සන්දර්භය තුළ$.ajax({url: "api/data", success: fooDone.bind(this)});
steve.sims

8
ප්‍රතික්‍රියා එක්-මාර්ග දත්ත බන්ධනයක් බැවින් මෙය ඇත්ත වශයෙන්ම වැරදියි
මැතිව් බ්‍රෙන්ට්

Att මැතිව්බ්‍රෙන්ට් ඔබ වැරදියි, නමුත් නිවැරදි නොවේ, ප්‍රතික්‍රියා මුක්කු වස්තුවක් වන අතර වෙනස් වුවහොත් ඒවා යෙදුම පුරාම වෙනස් වේ, නමුත් එය ප්‍රතික්‍රියා සංවර්ධකයා විසින් එය භාවිතා කිරීමට නිර්දේශ කරන ක්‍රමයක් නොවේ ...
Alireza

98

ජාවාස්ක්‍රිප්ට් හි 'අභිරහස්' සමඟ පොරබදමින් සිටියදී අප මුහුණ දෙන ඉතා පොදු ගැටළුවකි. අද මම මෙම අභිරහස අවමානයට ලක් කිරීමට උත්සාහ කරමි.

සරල ජාවාස්ක්‍රිප්ට් ශ්‍රිතයකින් ආරම්භ කරමු:

function foo(){
// do something 
 return 'wohoo';
}

let bar = foo(); // bar is 'wohoo' here

එය සරල සමමුහුර්ත ශ්‍රිත ඇමතුමකි (එහිදී එක් එක් කේත පේළිය ඊළඟට අනුපිළිවෙලට පෙර 'එහි කාර්යය අවසන් කර ඇත'), සහ ප්‍රති result ලය බලාපොරොත්තු වූ ආකාරයටම වේ.

දැන් අපගේ ශ්‍රිතයේ සුළු ප්‍රමාදයක් හඳුන්වා දීමෙන් අපි ටිකක් විකෘති කිරීම් එකතු කරමු, එවිට සියලු කේත පේළි අනුපිළිවෙලින් 'අවසන්' නොවේ. මේ අනුව, එය ක්‍රියාකාරීත්වයේ අසමමුහුර්ත හැසිරීම අනුකරණය කරයි:

function foo(){
 setTimeout( ()=>{
   return 'wohoo';
  }, 1000 )
}

let bar = foo() // bar is undefined here

ඉතින් ඔබ එහි යන්න, එම ප්‍රමාදය අප බලාපොරොත්තු වූ ක්‍රියාකාරිත්වය බිඳ දැමුවා! නමුත් හරියටම සිදුවූයේ කුමක්ද? හොඳයි, ඔබ කේතය දෙස බැලුවහොත් එය ඇත්තෙන්ම තර්කානුකූලයි. ශ්‍රිතය foo(), ක්‍රියාත්මක කිරීමෙන් පසු කිසිවක් ලබා undefinedනොදේ (මේ අනුව ආපසු ලබා දුන් අගය වේ ), නමුත් එය ටයිමරයක් ආරම්භ කරයි, එය 1s පසු ශ්‍රිතයක් 'wohoo' නැවත ලබා දෙයි. නමුත් ඔබට පෙනෙන පරිදි, බාර්එක වෙත පවරා ඇති වටිනාකම foo () වෙතින් වහාම ආපසු ලබා දෙන දේවල් වේ, එය කිසිවක් නොවේ undefined.

ඉතින්, අපි මෙම ගැටළුව විසඳන්නේ කෙසේද?

පොරොන්දුවක් සඳහා අපගේ කාර්යය විමසමු . පොරොන්දුව යනු සැබවින්ම එහි තේරුමයි: එයින් අදහස් කරන්නේ අනාගතයේදී ලැබෙන ඕනෑම නිමැවුමක් ලබා දීමට ශ්‍රිතය ඔබට සහතික වන බවයි. එබැවින් ඉහත අපගේ කුඩා ගැටලුව සඳහා එය ක්‍රියාකාරී ලෙස බලමු:

function foo(){
   return new Promise( (resolve, reject) => { // I want foo() to PROMISE me something
    setTimeout ( function(){ 
      // promise is RESOLVED , when execution reaches this line of code
       resolve('wohoo')// After 1 second, RESOLVE the promise with value 'wohoo'
    }, 1000 )
  })
}

let bar ; 
foo().then( res => {
 bar = res;
 console.log(bar) // will print 'wohoo'
});

මේ අනුව, සාරාංශය නම් - අජැක්ස් පාදක ඇමතුම් වැනි අසමමුහුර්ත කාර්යයන් නිරාකරණය කිරීම සඳහා, ඔබට resolveවටිනාකමට පොරොන්දුවක් භාවිතා කළ හැකිය (ඔබ නැවත පැමිණීමට අදහස් කරන). මේ අනුව, කෙටියෙන් ඔබ අසමමුහුර්ත කාර්යයන් වලදී නැවත පැමිණීම වෙනුවට අගය නිරාකරණය කරයි.

යාවත්කාලීන කිරීම (අසින්ක් සමඟ පොරොන්දු / බලා සිටින්න)

then/catchපොරොන්දු සමඟ වැඩ කිරීමට භාවිතා කිරීමට අමතරව , තවත් එක් ප්‍රවේශයක් තිබේ. මෙහි අදහස වන්නේ යම් අසමමිතික කාර්යය හඳුනා පසුව පොරොන්දු බලා විසඳීම සඳහා, කේතය ඊළඟ රේඛාව වෙත යාමට පෙර. එය තවමත් promisesහුඩ් යට ය, නමුත් වෙනස් සින්ටැක්ටිකල් ප්‍රවේශයකින්. දේවල් වඩාත් පැහැදිලි කර ගැනීම සඳහා, ඔබට පහත සංසන්දනයක් සොයාගත හැකිය:

ඉන්පසු / ඇල්ලීමේ අනුවාදය:

function saveUsers(){
     getUsers()
      .then(users => {
         saveSomewhere(users);
      })
      .catch(err => {
          console.error(err);
       })
 }

async / wait version:

  async function saveUsers(){
     try{
        let users = await getUsers()
        saveSomewhere(users);
     }
     catch(err){
        console.error(err);
     }
  }

පොරොන්දුවකින් වටිනාකමක් ලබා දීමට හෝ අසංක්කා / බලා සිටීමට හොඳම ක්‍රමය මෙය ලෙස තවමත් සලකන්නේද?
edwardsmarkf

3
wardedwardsmarkf පුද්ගලිකව මම හිතන්නේ නැහැ මේ වගේ හොඳම ක්‍රමයක් තියෙනවා කියලා. මගේ කේතයේ අසින්ක් කොටස් සඳහා මම එවකට / ඇල්ලීම, අසින්ක් / බලා සිටීම මෙන්ම ජනක යන්ත්‍ර සමඟ පොරොන්දු භාවිතා කරමි. එය බොහෝ දුරට භාවිතයේ සන්දර්භය මත රඳා පවතී.
අනීෂ් කේ.

96

අසමමුහුර්ත ශ්‍රිතයකින් අගයක් ලබා දීම සඳහා තවත් ප්‍රවේශයක් නම්, අසමමුහුර්ත ශ්‍රිතයේ ප්‍රති result ලය ගබඩා කරන වස්තුවක් තුළට යාමයි.

මෙන්න ඒ සඳහා උදාහරණයක්:

var async = require("async");

// This wires up result back to the caller
var result = {};
var asyncTasks = [];
asyncTasks.push(function(_callback){
    // some asynchronous operation
    $.ajax({
        url: '...',
        success: function(response) {
            result.response = response;
            _callback();
        }
    });
});

async.parallel(asyncTasks, function(){
    // result is available after performing asynchronous operation
    console.log(result)
    console.log('Done');
});

මම භාවිතා කරන්නේ resultඅසමමුහුර්ත මෙහෙයුමේදී අගය ගබඩා වස්තුව . අසමමුහුර්ත රැකියාවෙන් පසුව වුවද ප්‍රති result ලය ලබා ගැනීමට මෙය ඉඩ දෙයි.

මම මෙම ප්‍රවේශය ගොඩක් භාවිතා කරමි. අඛණ්ඩ මොඩියුල හරහා ප්‍රති result ලය නැවත රැහැන්ගත කිරීම සම්බන්ධව මෙම ප්‍රවේශය කෙතරම් හොඳින් ක්‍රියාත්මක වේදැයි දැන ගැනීමට මම උනන්දු වෙමි.


9
මෙහි වස්තුවක් භාවිතා කිරීම පිළිබඳ විශේෂ දෙයක් නොමැත. ඔබ ඔහුගේ ප්‍රතිචාරය කෙලින්ම පැවරුවහොත් එයද ක්‍රියාත්මක වේ result. අසින්ක් ශ්‍රිතය අවසන් වූ පසු ඔබ විචල්‍යය කියවන බැවින් එය ක්‍රියාත්මක වේ.
ෆීලික්ස් ක්ලින්ග්

85

පොරොන්දු සහ ඇමතුම් ලබා ගැනීම බොහෝ අවස්ථාවන්හිදී හොඳින් ක්‍රියාත්මක වන අතර, පසුපස යමක් වැනි දෙයක් ප්‍රකාශ කිරීම වේදනාවකි:

if (!name) {
  name = async1();
}
async2(name);

ඔබ අවසන් වනු ඇත async1; nameනිර්වචනය කර තිබේද නැද්ද යන්න පරීක්ෂා කර ඒ අනුව ඇමතුම් ලබා ගන්න.

async1(name, callback) {
  if (name)
    callback(name)
  else {
    doSomething(callback)
  }
}

async1(name, async2)

කුඩා උදාහරණ වලින් එය කමක් නැතත්, ඔබට සමාන අවස්ථා සහ දෝෂ හැසිරවීම් ඇති විට එය කරදරයක් වේ.

Fibers ගැටළුව විසඳීමට උපකාරී වේ.

var Fiber = require('fibers')

function async1(container) {
  var current = Fiber.current
  var result
  doSomething(function(name) {
    result = name
    fiber.run()
  })
  Fiber.yield()
  return result
}

Fiber(function() {
  var name
  if (!name) {
    name = async1()
  }
  async2(name)
  // Make any number of async calls from here
}

ඔබට මෙහි ව්‍යාපෘතිය පරීක්ෂා කළ හැකිය .


1
crecurf - එය මගේ ව්‍යාපෘතිය නොවේ. ඔබට ඔවුන්ගේ ගැටළු ට්රැකර් භාවිතා කිරීමට උත්සාහ කළ හැකිය.
rohithpr

1
මෙය ජනක යන්ත්‍ර ක්‍රියාකාරිත්වයට සමානද? developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/... *
Emanegux

1
මෙය තවමත් අදාළද?
අළුආන් හඩාඩ්

ඔබ async-awaitනෝඩ් හි නවතම අනුවාද කිහිපයක් භාවිතා කරන්නේ නම් ඔබට එය භාවිතා කළ හැකිය . යමෙකු පැරණි අනුවාද සමඟ සිරවී ඇත්නම් ඔවුන්ට මෙම ක්‍රමය භාවිතා කළ හැකිය.
rohithpr

83

මා ලියා ඇති පහත උදාහරණයෙන් දැක්වෙන්නේ කෙසේද යන්නයි

  • අසමමුහුර්ත HTTP ඇමතුම් හසුරුවන්න;
  • සෑම API ඇමතුමකින්ම ප්‍රතිචාර ලැබෙන තෙක් බලා සිටින්න;
  • පොරොන්දු රටාව භාවිතා කරන්න ;
  • භාවිත බහු HTTP ඇමතුම් වලට සම්බන්ධ වීමට Promise.all රටාව ;

මෙම ක්‍රියාකාරී උදාහරණය ස්වයං අන්තර්ගතය. XMLHttpRequestඇමතුම් ලබා ගැනීම සඳහා කවුළු වස්තුව භාවිතා කරන සරල ඉල්ලීම් වස්තුවක් එය අර්ථ දක්වනු ඇත . පොරොන්දු රාශියක් සම්පූර්ණ වන තෙක් බලා සිටීම සඳහා සරල කාර්යයක් එය අර්ථ දක්වනු ඇත.

සන්දර්භය. උදාහරණය වන්නේ සෙවීම සඳහා Spotify වෙබ් API අන්ත ලක්ෂ්‍යය විමසීමයිplaylist දී ඇති විමසුම් නූල් සමූහයක් වස්තු :

[
 "search?type=playlist&q=%22doom%20metal%22",
 "search?type=playlist&q=Adele"
]

සෑම අයිතමයක් සඳහාම, නව පොරොන්දුවක් අවහිර කරනු ඇත - ExecutionBlock, ප්‍රති result ලය විග්‍රහ කරන්න, ප්‍රති result ල අරාව මත පදනම්ව නව පොරොන්දු මාලාවක් උපලේඛනගත කරන්න, එය Spotify ලැයිස්තුවකිuser වස්තු අතර නව HTTP ඇමතුම ExecutionProfileBlockඅසමමුහුර්තව ක්‍රියාත්මක කරයි.

එවිට ඔබට කූඩුවල පොරොන්දු ව්‍යුහයක් දැක ගත හැකි අතර, එමඟින් ඔබට බහු හා සම්පූර්ණයෙන්ම අසමමුහුර්ත කැදැලි සහිත HTTP ඇමතුම් ලබා ගැනීමට ඉඩ සලසයි, සහ එක් එක් ඇමතුම් උප කාණ්ඩයේ ප්‍රති results ල සමඟ සම්බන්ධ වන්න. Promise.all .

සටහන මෑත කාලීන Spotifysearch API වලට ඉල්ලීම් ශීර්ෂයන්හි සඳහන් කිරීමට ප්‍රවේශ ටෝකනයක් අවශ්‍ය වේ:

-H "Authorization: Bearer {your access token}" 

එබැවින්, පහත දැක්වෙන උදාහරණය ක්‍රියාත්මක කිරීම සඳහා ඔබේ ප්‍රවේශ ටෝකනය ඉල්ලීම් ශීර්ෂයන්හි තැබිය යුතුය:

var spotifyAccessToken = "YourSpotifyAccessToken";
var console = {
    log: function(s) {
        document.getElementById("console").innerHTML += s + "<br/>"
    }
}

// Simple XMLHttpRequest
// based on https://davidwalsh.name/xmlhttprequest
SimpleRequest = {
    call: function(what, response) {
        var request;
        if (window.XMLHttpRequest) { // Mozilla, Safari, ...
            request = new XMLHttpRequest();
        } else if (window.ActiveXObject) { // Internet Explorer
            try {
                request = new ActiveXObject('Msxml2.XMLHTTP');
            }
            catch (e) {
                try {
                  request = new ActiveXObject('Microsoft.XMLHTTP');
                } catch (e) {}
            }
        }

        // State changes
        request.onreadystatechange = function() {
            if (request.readyState === 4) { // Done
                if (request.status === 200) { // Complete
                    response(request.responseText)
                }
                else
                    response();
            }
        }
        request.open('GET', what, true);
        request.setRequestHeader("Authorization", "Bearer " + spotifyAccessToken);
        request.send(null);
    }
}

//PromiseAll
var promiseAll = function(items, block, done, fail) {
    var self = this;
    var promises = [],
                   index = 0;
    items.forEach(function(item) {
        promises.push(function(item, i) {
            return new Promise(function(resolve, reject) {
                if (block) {
                    block.apply(this, [item, index, resolve, reject]);
                }
            });
        }(item, ++index))
    });
    Promise.all(promises).then(function AcceptHandler(results) {
        if (done) done(results);
    }, function ErrorHandler(error) {
        if (fail) fail(error);
    });
}; //promiseAll

// LP: deferred execution block
var ExecutionBlock = function(item, index, resolve, reject) {
    var url = "https://api.spotify.com/v1/"
    url += item;
    console.log( url )
    SimpleRequest.call(url, function(result) {
        if (result) {

            var profileUrls = JSON.parse(result).playlists.items.map(function(item, index) {
                return item.owner.href;
            })
            resolve(profileUrls);
        }
        else {
            reject(new Error("call error"));
        }
    })
}

arr = [
    "search?type=playlist&q=%22doom%20metal%22",
    "search?type=playlist&q=Adele"
]

promiseAll(arr, function(item, index, resolve, reject) {
    console.log("Making request [" + index + "]")
    ExecutionBlock(item, index, resolve, reject);
}, function(results) { // Aggregated results

    console.log("All profiles received " + results.length);
    //console.log(JSON.stringify(results[0], null, 2));

    ///// promiseall again

    var ExecutionProfileBlock = function(item, index, resolve, reject) {
        SimpleRequest.call(item, function(result) {
            if (result) {
                var obj = JSON.parse(result);
                resolve({
                    name: obj.display_name,
                    followers: obj.followers.total,
                    url: obj.href
                });
            } //result
        })
    } //ExecutionProfileBlock

    promiseAll(results[0], function(item, index, resolve, reject) {
        //console.log("Making request [" + index + "] " + item)
        ExecutionProfileBlock(item, index, resolve, reject);
    }, function(results) { // aggregated results
        console.log("All response received " + results.length);
        console.log(JSON.stringify(results, null, 2));
    }

    , function(error) { // Error
        console.log(error);
    })

    /////

  },
  function(error) { // Error
      console.log(error);
  });
<div id="console" />

මම දීර්ඝ වශයෙන් මෙම විසඳුම සාකච්ඡා කර තිබෙනවා මෙතන .


80

කෙටි පිළිතුර නම්, ඔබ මෙවැනි ඇමතුමක් ක්‍රියාත්මක කළ යුතුය:

function callback(response) {
    // Here you can do what ever you want with the response object.
    console.log(response);
}

$.ajax({
    url: "...",
    success: callback
});

78

2017 පිළිතුර: සෑම වත්මන් බ්‍රව්සරයකම සහ නෝඩයකම ඔබට අවශ්‍ය දේ දැන්ම කළ හැකිය

මෙය තරමක් සරල ය:

  • පොරොන්දුවක් ආපසු දෙන්න
  • 'බලා සිටින්න' භාවිතා කරන්න සිටින්න , එමඟින් ජාවාස්ක්‍රිප්ට් වෙත වටිනාකමක් (HTTP ප්‍රතිචාරය වැනි) විසඳා ගැනීමේ පොරොන්දුව බලාපොරොත්තුවෙන් සිටින ලෙස පවසනු ඇත.
  • මව් ශ්‍රිතයට 'අසින්ක්' යතුර එක් කරන්න

මෙන්න ඔබේ කේතයේ ක්‍රියාකාරී අනුවාදය:

(async function(){

var response = await superagent.get('...')
console.log(response)

})()

වත්මන් බ්‍රව්සර් සහ නෝඩ් 8 හි රැඳී සිටීම සහාය දක්වයි


7
අවාසනාවට, මෙය ක්‍රියාත්මක වන්නේ පොරොන්දු ලබා දෙන කාර්යයන් සමඟ පමණි - උදාහරණයක් ලෙස එය ඇමතුම් ලබා ගන්නා Node.js API සමඟ ක්‍රියා නොකරයි. සෑම කෙනෙකුම "වත්මන් බ්‍රව්සර්" භාවිතා නොකරන නිසා මම බාබෙල් නොමැතිව එය භාවිතා කිරීම නිර්දේශ නොකරමි.
මයිකල් පෙරකෝව්ස්කි

2
@ MichałPerłakowski node 8 හි nodejs.org/api/util.html#util_util_promisify_original ඇතුළත් වන අතර එය node.js API නැවත පොරොන්දු ලබා දීමට භාවිතා කළ හැකිය. වත්මන් නොවන බ්‍රව්සර් සඳහා සහය දැක්වීමට ඔබට කාලය හා මුදල් තිබේද යන්න පැහැදිලිවම ඔබගේ තත්වය මත රඳා පවතී.
mikemaccana

IE 11 තවමත් 2018 හි වර්තමාන බ්‍රව්සරයකි, කනගාටුවට කරුණක් වන අතර එය සහාය නොදක්වයිawait/async
ජුවාන් මෙන්ඩිස්

IE11 වත්මන් බ්‍රව්සරයක් නොවේ. එය මීට වසර 5 කට පෙර නිකුත් කරන ලද අතර, කැනියස් අනුව ලෝක ව්‍යාප්ත වෙළඳපල කොටස 2.5% ක් වන අතර, වර්තමාන තාක්‍ෂණය නොසලකා හැරීමට යමෙකු ඔබේ අයවැය දෙගුණ කරන්නේ නම් එය බොහෝ මිනිසුන්ගේ කාලය වටින්නේ නැත.
mikemaccana

76

Js යනු තනි නූල් වර්ගයකි.

බ්‍රව්සරය කොටස් තුනකට බෙදිය හැකිය:

1) සිදුවීම් ලූපය

2) වෙබ් API

3) සිදුවීම් පෝලිම

සිදුවීම් ලූපය සදහටම ක්‍රියාත්මක වේ, එනම් එක්තරා ආකාරයක අසීමිත පුඩුවක්. එවරන්ට් පෝලිම් යනු ඔබගේ සියලු ක්‍රියාකාරකම් කිසියම් සිදුවීමක් මතට තල්ලු කරනු ලැබේ (උදාහරණය: ක්ලික් කරන්න) මෙය එකින් එක පෝලිම් වලින් සිදු කර සිදුවීම් ලූපයට දමා මෙම ශ්‍රිතය ක්‍රියාත්මක කර එය ස්වයංක්‍රීයව සකස් කරයි පළමු එක ක්‍රියාත්මක කිරීමෙන් පසු ඊළඟ එක සඳහා. මෙයින් අදහස් කරන්නේ එක් ශ්‍රිතයක් පෝලිමේ ඇති ශ්‍රිතය සිදුවීම් ලූපය තුළ ක්‍රියාත්මක වන තෙක් ක්‍රියාත්මක නොවන බවයි.

දැන් අපි හිතන්නේ අපි පෝලිමක ශ්‍රිත දෙකක් තල්ලු කළෙමු. එකක් සේවාදායකයෙන් දත්ත ලබා ගැනීම සඳහා වන අතර තවත් එකක් එම දත්ත භාවිතා කරයි. අපි සර්වර් රෙක්ස්ට් () ශ්‍රිතය පෝලිමේ තල්ලු කර මුලින්ම ඩේටා () ශ්‍රිතය භාවිතා කරමු. serverRequest ශ්‍රිතය සිදුවීම් ලූපය තුළට ගොස් සේවාදායකයාට ඇමතුමක් ලබා දෙන්නේ සේවාදායකයෙන් දත්ත ලබා ගැනීමට කොපමණ කාලයක් ගතවේදැයි අපි නොදනිමු. එබැවින් මෙම ක්‍රියාවලියට කාලය ගතවනු ඇතැයි අපේක්ෂා කරන අතර අපගේ සිදුවීම් ලූපය කාර්යබහුල වන පරිදි අපගේ පිටුව එල්ලා තබන්නෙමු. ඒපීඅයි කාර්යභාරය ඉටු කරන අතර එය මෙම සිදුවීම සිදුවීම් ලූපයෙන් ලබා ගන්නා අතර අපට සිදුවීම් ලූපය නොමිලේ ලබා දීම සමඟ ගනුදෙනු කරයි. එවිට අපට ඊළඟ ශ්‍රිතය පෝලිමේ සිට ක්‍රියාත්මක කළ හැකිය. පෝලිමේ ඊළඟ කාර්යය වන්නේ උපයෝගීතා දත්ත () වන අතර එය ලූපයට යන නමුත් දත්ත නොමැති නිසා එය යයි ඊළඟ ශ්‍රිතය නාස්ති කිරීම සහ ක්‍රියාත්මක කිරීම පෝලිමේ අවසානය දක්වාම පවතී. (මෙය අසින්ක් කෝලිං ලෙස හැඳින්වේ, එනම් දත්ත ලබා ගන්නා තෙක් අපට වෙනත් දෙයක් කළ හැකිය)

අපගේ සේවාදායක ඉල්ලීම් () ශ්‍රිතයට කේතයක් තුළ ආපසු ප්‍රකාශයක් තිබේ යැයි සිතමු, අපි සේවාදායක වෙබ් API වෙතින් දත්ත ආපසු ලබා ගන්නා විට එය පෝලිම් අවසානයේ පෝලිමේ තල්ලු කරනු ඇත. එය පෝලිමේ අවසානයේ තල්ලු වන විට අපට මෙම දත්ත උපයෝගී කර ගත නොහැක, මන්ද මෙම දත්ත උපයෝගී කර ගැනීම සඳහා අපගේ පෝලිමේ කිසිදු කාර්යයක් ඉතිරිව නොමැත. මේ අනුව අසින්ක් කෝල් වෙතින් යමක් ආපසු ලබා දිය නොහැක.

මේ අනුව විසඳුම ඇමතුම හෝ පොරොන්දුවයි .

මෙහි ඇති එක් පිළිතුරක පින්තූරයක්, ඇමතුම් ආපසු ගැනීම නිවැරදිව පැහැදිලි කරයි ... අපි අපගේ ක්‍රියාකාරිත්වය (සේවාදායකයෙන් ආපසු ලබා දුන් දත්ත උපයෝගී කර ගනිමින්) ක්‍රියාකාරී ඇමතුම් සේවාදායකයට ලබා දෙමු.

ආපසු අමතන්න

 function doAjax(callbackFunc, method, url) {
  var xmlHttpReq = new XMLHttpRequest();
  xmlHttpReq.open(method, url);
  xmlHttpReq.onreadystatechange = function() {

      if (xmlHttpReq.readyState == 4 && xmlHttpReq.status == 200) {
        callbackFunc(xmlHttpReq.responseText);
      }


  }
  xmlHttpReq.send(null);

}

මගේ කේතය තුළ එය හැඳින්වෙන්නේ

function loadMyJson(categoryValue){
  if(categoryValue==="veg")
  doAjax(print,"GET","http://localhost:3004/vegetables");
  else if(categoryValue==="fruits")
  doAjax(print,"GET","http://localhost:3004/fruits");
  else 
  console.log("Data not found");
}

Javscript.info ඇමතුම්


68

දුරස්ථ ඇමතුමක් ලබා ගැනීමට ඔබට මෙම අභිරුචි පුස්තකාලය (පොරොන්දුව භාවිතා කර ලියා ඇත) භාවිතා කළ හැකිය.

function $http(apiConfig) {
    return new Promise(function (resolve, reject) {
        var client = new XMLHttpRequest();
        client.open(apiConfig.method, apiConfig.url);
        client.send();
        client.onload = function () {
            if (this.status >= 200 && this.status < 300) {
                // Performs the function "resolve" when this.status is equal to 2xx.
                // Your logic here.
                resolve(this.response);
            }
            else {
                // Performs the function "reject" when this.status is different than 2xx.
                reject(this.statusText);
            }
        };
        client.onerror = function () {
            reject(this.statusText);
        };
    });
}

සරල භාවිත උදාහරණය:

$http({
    method: 'get',
    url: 'google.com'
}).then(function(response) {
    console.log(response);
}, function(error) {
    console.log(error)
});

67

තවත් විසඳුමක් වන්නේ අනුක්‍රමික ක්‍රියාකරු nsynjs හරහා කේතය ක්‍රියාත්මක කිරීමයි .

යටින් පවතින ක්‍රියාකාරිත්වය සහතික කර ඇත්නම්

nsynjs විසින් සියලු පොරොන්දු අනුපිළිවෙලින් ඇගයීමට ලක් කරනු ඇති අතර පොරොන්දු ප්‍රති result ල dataදේපල බවට පත් කරනු ඇත :

function synchronousCode() {

    var getURL = function(url) {
        return window.fetch(url).data.text().data;
    };
    
    var url = 'https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js';
    console.log('received bytes:',getURL(url).length);
    
};

nsynjs.run(synchronousCode,{},function(){
    console.log('synchronousCode done');
});
<script src="https://rawgit.com/amaksr/nsynjs/master/nsynjs.js"></script>

යටින් පවතින ක්‍රියාකාරීත්වය සහතික කර නොමැති නම්

පියවර 1. ඇමතුම සමඟ ක්‍රියාකාරීත්වය nsynjs- දැනුවත් එතීමට ඔතා (එය සහතික කළ අනුවාදයක් තිබේ නම්, ඔබට මෙම පියවර මඟ හැරිය හැක):

var ajaxGet = function (ctx,url) {
    var res = {};
    var ex;
    $.ajax(url)
    .done(function (data) {
        res.data = data;
    })
    .fail(function(e) {
        ex = e;
    })
    .always(function() {
        ctx.resume(ex);
    });
    return res;
};
ajaxGet.nsynjsHasCallback = true;

පියවර 2. සමමුහුර්ත තර්කනය ක්‍රියාත්මක කරන්න:

function process() {
    console.log('got data:', ajaxGet(nsynjsCtx, "data/file1.json").data);
}

පියවර 3. nsynjs හරහා ක්‍රියාකාරීත්වය සමමුහුර්තව ක්‍රියාත්මක කරන්න:

nsynjs.run(process,this,function () {
    console.log("synchronous function finished");
});

Nsynjs විසින් සියලු ක්‍රියාකරුවන් සහ ප්‍රකාශන පියවරෙන් පියවර ඇගයීමට ලක් කරනු ඇත, මන්දගාමී ක්‍රියාකාරිත්වයේ ප්‍රති result ලයක් සුදානම් නොවන්නේ නම් එය ක්‍රියාත්මක කිරීම නවතා දමයි.

මෙහි තවත් උදාහරණ: https://github.com/amaksr/nsynjs/tree/master/examples


2
මෙය සිත්ගන්නා සුළුය. වෙනත් භාෂාවලින් ඔබ එය කරන ආකාරයට අසින්ක් කෝඩ් කිරීමට එය ඉඩ දෙන ආකාරය මම කැමතියි. නමුත් තාක්ෂණික වශයෙන් එය සැබෑ ජාවාස්ක්‍රිප්ට් නොවේද?
ජේ මොරිස්

41

ECMAScript 6 හි 'උත්පාදක යන්ත්ර' ඇති අතර එමඟින් ඔබට පහසුවෙන් අසමමුහුර්ත ශෛලියකින් වැඩසටහන්ගත කළ හැකිය.

function* myGenerator() {
    const callback = yield;
    let [response] = yield $.ajax("https://stackoverflow.com", {complete: callback});
    console.log("response is:", response);

    // examples of other things you can do
    yield setTimeout(callback, 1000);
    console.log("it delayed for 1000ms");
    while (response.statusText === "error") {
        [response] = yield* anotherGenerator();
    }
}

ඉහත කේතය ක්‍රියාත්මක කිරීම සඳහා ඔබ මෙය කරන්නේ:

const gen = myGenerator(); // Create generator
gen.next(); // Start it
gen.next((...args) => gen.next([...args])); // Set its callback function

ඔබට ES6 සඳහා සහය නොදක්වන බ්‍රව්සර් ඉලක්ක කිරීමට අවශ්‍ය නම් ඔබට ECMAScript 5 ජනනය කිරීම සඳහා කේතය බාබෙල් හෝ වසා දැමීමේ-සම්පාදකය හරහා ධාවනය කළ හැකිය.

ඇමතුම් ආපසු ...argsඅරාවකින් ඔතා ඇති අතර ඔබ ඒවා කියවන විට විනාශ වේ, එවිට රටාවට බහුවිධ තර්ක ඇති ඇමතුම් සමඟ සාර්ථකව කටයුතු කළ හැකිය. උදාහරණයක් ලෙස node fs සමඟ :

const [err, data] = yield fs.readFile(filePath, "utf-8", callback);

39

අසමමුහුර්ත ඉල්ලීම් සමඟ වැඩ කිරීම සඳහා ප්‍රවේශයන් කිහිපයක් මෙන්න:

  1. බ්‍රව්සර් පොරොන්දු වස්තුව
  2. Q - JavaScript සඳහා පොරොන්දුව පුස්තකාලය
  3. A + Promises.js
  4. jQuery කල් දමා ඇත
  5. XMLHttpRequest API
  6. ඇමතුම් ලබා ගැනීමේ සංකල්පය භාවිතා කිරීම - පළමු පිළිතුර ක්‍රියාත්මක කිරීම ලෙස

උදාහරණය: බහුවිධ ඉල්ලීම් සමඟ වැඩ කිරීම සඳහා jQuery ක්‍රියාත්මක කිරීම කල් දැමීය

var App = App || {};

App = {
    getDataFromServer: function(){

      var self = this,
                 deferred = $.Deferred(),
                 requests = [];

      requests.push($.getJSON('request/ajax/url/1'));
      requests.push($.getJSON('request/ajax/url/2'));

      $.when.apply(jQuery, requests).done(function(xhrResponse) {
        return deferred.resolve(xhrResponse.result);
      });
      return deferred;
    },

    init: function(){

        this.getDataFromServer().done(_.bind(function(resp1, resp2) {

           // Do the operations which you wanted to do when you
           // get a response from Ajax, for example, log response.
        }, this));
    }
};
App.init();


38

අප "කාලය" ලෙස හඳුන්වන මානයකින් ඉදිරියට යන විශ්වයක අප සිටිනු ඇත. කාලය යනු කුමක්දැයි අපට සැබවින්ම වැටහෙන්නේ නැත, නමුත් අප විසින් වියුක්ත කිරීම් සහ වාග් මාලාව වර්ධනය කර ඇති අතර ඒ පිළිබඳව අපට තර්ක කිරීමට හා කතා කිරීමට ඉඩ සලසයි: "අතීතය", "වර්තමානය", "අනාගතය", "පෙර", "පසු".

අප ගොඩනඟන පරිගණක පද්ධති - වැඩි වැඩියෙන් - වැදගත් මානයක් ලෙස කාලය ඇත. සමහර දේවල් අනාගතයේදී සිදුවීමට නියමිතය. පළමු දේ අවසානයේදී සිදු වූ පසු වෙනත් දේ සිදුවිය යුතුය. "අසමමුහුර්තතාව" යනුවෙන් හැඳින්වෙන මූලික මතය මෙයයි. අපගේ වැඩි වැඩියෙන් ජාලගත ලෝකයේ, අසමමුහුර්තතාවයේ වඩාත් පොදු අවස්ථාව වන්නේ යම් දුරස්ථ පද්ධතියක් යම් ඉල්ලීමකට ප්‍රතිචාර දක්වන තෙක් බලා සිටීමයි.

උදාහරණයක් සලකා බලන්න. ඔබ කිරි දෙන්නා අමතා කිරි ටිකක් ඇණවුම් කරන්න. එය පැමිණි විට, එය ඔබේ කෝපි තුළට දැමීමට ඔබට අවශ්‍යය. ඔබට දැන් ඔබේ කෝපි වල කිරි දැමිය නොහැක, මන්ද එය තවමත් මෙහි නොමැති බැවිනි. ඔබේ කෝපි තුළට දැමීමට පෙර එය පැමිණෙන තෙක් ඔබ බලා සිටිය යුතුය. වෙනත් වචන වලින් කිවහොත්, පහත සඳහන් දෑ ක්‍රියා නොකරනු ඇත:

var milk = order_milk();
put_in_coffee(milk);

JS එය කිරීමට අවශ්ය බව දැන ගැනීමට කිසිදු ක්රමයක් නොමැති නිසා බලා සඳහා order_milkඑය ඉටු පෙර අවසන් කිරීමට put_in_coffee. වෙනත් වචන වලින් කිවහොත්, එය දන්නේ නැහැ ඒ ඇයි order_milkවේ අසමමිතික අනාගත යම් කාලයක් දක්වා කිරි සිදු කිරීමට යන්නේ නැති බව --is දෙයක්. ජේ.

මෙම ගැටළුවට සම්භාව්‍ය ජේඑස් ප්‍රවේශය, ජේඑස් විසින් පළමු පන්තියේ වස්තූන් ලෙස ක්‍රියා කළ හැකි අතර එයින් සම්මත කළ හැකි වන්නේ, අසමමුහුර්ත ඉල්ලීම සඳහා පරාමිතියක් ලෙස ශ්‍රිතයක් සම්මත කිරීමයි, එය සම්පූර්ණ වූ විට එය ක්‍රියාත්මක වේ. අනාගතයේ දී එහි කර්තව්‍යය. එය "ඇමතුම් ආපසු" ප්‍රවේශයයි. එය මේ වගේ ය:

order_milk(put_in_coffee);

order_milkපයින් ගසයි, කිරි ඇණවුම් කරයි, පසුව, එය පැමිණෙන විට සහ පමණක් එය ඉල්ලා put_in_coffeeසිටී.

මෙම ඇමතුම් ආපසු ගැනීමේ ප්‍රවේශයේ ඇති ගැටළුව නම්, එහි ප්‍රති result ලය වාර්තා කරන ශ්‍රිතයක සාමාන්‍ය අර්ථ නිරූපණය දූෂණය කිරීමයි return; ඒ වෙනුවට, පරාමිතියක් ලෙස ලබා දී ඇති ඇමතුමක් ලබා දීමෙන් කාර්යයන් ඒවායේ ප්‍රති results ල වාර්තා නොකළ යුතුය. එසේම, සිදුවීම්වල දීර් sequ අනුපිළිවෙල සමඟ කටයුතු කිරීමේදී මෙම ප්‍රවේශය වේගයෙන් නොසැලකිලිමත් විය හැකිය. උදාහරණයක් ලෙස, කෝපි වල කිරි දමනු ලබන තෙක් බලා සිටීමට මට අවශ්‍ය යැයි කියමු, ඉන්පසු තුන්වන පියවරක් කරන්න, එනම් කෝපි පානය කිරීම. මට මේ වගේ දෙයක් ලිවීමට අවශ්‍යයි:

order_milk(function(milk) { put_in_coffee(milk, drink_coffee); }

එහිදී මම put_in_coffeeකිරි දෙකටම දැමිය යුතු අතර, කිරි දැමූ පසු ක්‍රියාත්මක කිරීමට ( drink_coffee) ක්‍රියා කරමි . එවැනි කේත ලිවීමට, කියවීමට හා නිදොස්කරණය කිරීමට අපහසු වේ.

මෙම අවස්ථාවේදී, අපට ප්‍රශ්නයේ කේතය නැවත ලිවිය හැකිය:

var answer;
$.ajax('/foo.json') . done(function(response) {
  callback(response.data);
});

function callback(data) {
  console.log(data);
}

පොරොන්දු ඇතුළත් කරන්න

මෙය යම් ආකාරයක අනාගතයක් හෝ අසමමුහුර්ත ප්‍රති come ලයක් නියෝජනය කරන විශේෂිත වටිනාකමක් වන “පොරොන්දුවක්” යන සංකල්පය සඳහා පෙළඹවීම විය . එය දැනටමත් සිදුවී ඇති දෙයක් හෝ අනාගතයේදී සිදුවීමට යන දෙයක් නිරූපණය කළ හැකිය, නැතහොත් කිසි විටෙකත් සිදු නොවනු ඇත. පොරොන්දුවලට තනි ක්‍රමයක් ඇත, නම් thenකර ඇති අතර, එම පොරොන්දුව නියෝජනය කරන ප්‍රති come ලය සාක්ෂාත් වූ විට ක්‍රියාත්මක කිරීමට ඔබ ක්‍රියා කරයි.

අපගේ කිරි සහ කෝපි පිළිබඳ පැමිණිල්ලේ දී, අපි නිර්මාණය order_milkපසුව, පැමිණෙන කිරි සඳහා පොරොන්දුව නැවත සඳහන් put_in_coffeeලෙස thenපහත සඳහන් පරිදි, ක්රියාකාරී:

order_milk() . then(put_in_coffee)

මෙහි ඇති එක් වාසියක් නම්, අනාගත සිදුවීම්වල අනුපිළිවෙලක් නිර්මාණය කිරීම සඳහා අපට මේවා එකට බැඳ තැබිය හැකිය ("දම්වැල"):

order_milk() . then(put_in_coffee) . then(drink_coffee)

ඔබගේ විශේෂිත ගැටලුවට පොරොන්දු ඉටු කරමු. අපගේ ඉල්ලීම් තර්කනය ශ්‍රිතයක් තුළට ඔතා, එය පොරොන්දුවක් ලබා දෙයි:

function get_data() {
  return $.ajax('/foo.json');
}

ඇත්ත වශයෙන්ම, අප කළ සියල්ලම returnඇමතුමට එකතු කිරීමක් පමණි $.ajax. මෙය ක්‍රියාත්මක වන්නේ jQuery විසින් $.ajaxදැනටමත් යම් ආකාරයක පොරොන්දුවක් වැනි දෙයක් ලබා දෙන බැවිනි. (ප්‍රායෝගිකව, විස්තර ලබා නොගෙන, සැබෑ පොරොන්දුවක් ලබා දීම සඳහා අපි මෙම ඇමතුම එතීමට කැමැත්තෙමු, නැතහොත් ඒ සඳහා වෙනත් විකල්පයක් භාවිතා $.ajaxකරමු.) දැන්, අපට ගොනුව පටවා එය අවසන් වන තෙක් බලා සිටීමට අවශ්‍ය නම් සහ ඉන්පසු යමක් කරන්න, අපට සරලව කිව හැකිය

get_data() . then(do_something)

උදාහරණයක් වශයෙන්,

get_data() . 
  then(function(data) { console.log(data); });

පොරොන්දු භාවිතා කරන විට, අපි බොහෝ කාර්යයන් පසුකර යන්නෙමු then, එබැවින් වඩාත් සංයුක්ත ES6- ශෛලීය ඊතල ශ්‍රිත භාවිතා කිරීම බොහෝ විට ප්‍රයෝජනවත් වේ:

get_data() . 
  then(data => console.log(data));

මෙම asyncමූල පදය

නමුත් සමමුහුර්ත නම් එක් ආකාරයකින් කේතය ලිවීමට හා අසමමුහුර්ත නම් ඊට වඩා වෙනස් ආකාරයකට තවමත් නොපැහැදිලි යමක් තිබේ. සමමුහුර්ත සඳහා, අපි ලියන්නෙමු

a();
b();

නමුත් aඅසමමුහුර්ත නම් , පොරොන්දු සහිතව අප ලිවිය යුතුය

a() . then(b);

ඉහළින්, අපි පැවසුවේ, "ජේඑස් හට දෙවන ඇමතුම ක්‍රියාත්මක කිරීමට පෙර පළමු ඇමතුම අවසන් වන තෙක් බලා සිටිය යුතු බව දැන ගැනීමට ක්‍රමයක් නැත ". කනගාටුයි එය එහි නම් ලස්සන වෙන්න විය බව JS කියන්න ක්රමයක්? await"අසින්ක්" ශ්‍රිතයක් ලෙස හැඳින්වෙන විශේෂ ආකාරයේ ශ්‍රිතයක් තුළ භාවිතා වන මූල පදය ඇති බව එයින් පෙනේ . මෙම අංගය ඊඑස් හි එළඹෙන අනුවාදයේ කොටසක් වන නමුත් නිවැරදි පෙරසිටුවීම් ලබා දී ඇති බාබෙල් වැනි ප්‍රවාහකයන්ගෙන් දැනටමත් ලබා ගත හැකිය. මෙය සරලව ලිවීමට අපට ඉඩ සලසයි

async function morning_routine() {
  var milk   = await order_milk();
  var coffee = await put_in_coffee(milk);
  await drink(coffee);
}

ඔබේ නඩුවේදී, ඔබට එවැනි දෙයක් ලිවීමට හැකි වනු ඇත

async function foo() {
  data = await get_data();
  console.log(data);
}

37

කෙටි පිළිතුර : ඔබගේ foo()ක්‍රමය වහාම නැවත පැමිණෙන අතර , ශ්‍රිතය නැවත පැමිණි පසු$ajax() ඇමතුම අසමමුහුර්තව ක්‍රියාත්මක වේ . ගැටළුව වන්නේ අසින්ක් ඇමතුම මඟින් ලබාගත් ප්‍රති results ල නැවත ලැබුණු පසු එය ගබඩා කරන්නේ කෙසේද යන්නයි.

මෙම ත්‍රෙඩ් එකේ විසඳුම් කිහිපයක් ලබා දී ඇත. සමහර විට පහසුම ක්‍රමය නම් වස්තුවක් foo()ක්‍රමයට යොමු කිරීම සහ අසින්ක් ඇමතුම අවසන් වූ පසු ප්‍රති object ල එම වස්තුවේ සාමාජිකයෙකු තුළ ගබඩා කිරීමයි.

function foo(result) {
    $.ajax({
        url: '...',
        success: function(response) {
            result.response = response;   // Store the async result
        }
    });
}

var result = { response: null };   // Object to hold the async result
foo(result);                       // Returns before the async completes

ඇමතුම foo()තවමත් ප්‍රයෝජනවත් කිසිවක් ලබා නොදෙන බව සලකන්න . කෙසේ වෙතත්, අසින්ක් ඇමතුමේ ප්‍රති result ලය දැන් ගබඩා වේ result.response.


14
මෙය ක්‍රියාත්මක වන අතර එය ගෝලීය විචල්‍යයකට පැවරීමට වඩා හොඳ නැත.
ෆීලික්ස් ක්ලින්ග්

36

සාර්ථකත්වය callback()තුළ ශ්‍රිතයක් භාවිතා කරන්න foo(). මේ ආකාරයෙන් උත්සාහ කරන්න. එය සරල හා තේරුම් ගැනීමට පහසුය.  

var lat = "";
var lon = "";
function callback(data) {
    lat = data.lat;
    lon = data.lon;
}
function getLoc() {
    var url = "http://ip-api.com/json"
    $.getJSON(url, function(data) {
        callback(data);
    });
}

getLoc();

29

ප්‍රශ්නය වූයේ:

අසමමුහුර්ත ඇමතුමකින් ප්‍රතිචාරය ලබා දෙන්නේ කෙසේද?

ඒවා අර්ථ දැක්විය හැක්කේ:

බවට පත් කර ගන්නේ කෙසේද අසමමිතික කේතය පෙනුම සමමුහුර්ත ?

විසඳුම වනුයේ ඇමතුම් ආපසු ගැනීම වළක්වා ගැනීම සහ පොරොන්දු සහ අසින්ක් / බලා සිටීම යන සංයෝජන භාවිතා කිරීමයි .

අජැක්ස් ඉල්ලීමක් සඳහා උදාහරණයක් දීමට මම කැමතියි.

(එය ජාවාස්ක්‍රිප්ට් වලින් ලිවිය හැකි වුවද, මම එය පයිතන්හි ලිවීමට කැමැත්තෙමි, ට්‍රාන්ස්ක්‍රිප්ට් භාවිතයෙන් එය ජාවාස්ක්‍රිප්ට් වෙත සම්පාදනය කරමි .

පළමු කිරීමට, jQuery භාවිතය හැකි ඉඩ දෙනවා $ලෙස ලබා ගත S:

__pragma__ ('alias', 'S', '$')

පොරොන්දුවක් ලබා දෙන ශ්‍රිතයක් නිර්වචනය කරන්න , මේ අවස්ථාවේ දී අජැක්ස් ඇමතුමක්:

def read(url: str):
    deferred = S.Deferred()
    S.ajax({'type': "POST", 'url': url, 'data': { },
        'success': lambda d: deferred.resolve(d),
        'error': lambda e: deferred.reject(e)
    })
    return deferred.promise()

අසමමුහුර්ත කේතය සමමුහුර්ත ලෙස භාවිතා කරන්න :

async def readALot():
    try:
        result1 = await read("url_1")
        result2 = await read("url_2")
    except Exception:
        console.warn("Reading a lot failed")

29

පොරොන්දුව භාවිතා කිරීම

මෙම ප්රශ්නයට වඩාත්ම පරිපූර්ණ පිළිතුර වන්නේ භාවිතා Promiseකිරීමයි.

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

භාවිතය

ajax("GET", "/test", "acrive=1").then(function(result) {
    // Code depending on result
})
.catch(function() {
    // An error occurred
});

නමුත් ඉන්න...!

පොරොන්දු භාවිතා කිරීමේ ගැටලුවක් තිබේ!

අප අපේම අභිරුචි පොරොන්දුවක් භාවිතා කළ යුත්තේ ඇයි?

පැරණි බ්‍රව්සර්වල දෝෂයක් ඇති බව දැනගන්නා තෙක් මම මෙම විසඳුම ටික කලක් භාවිතා කළෙමි:

Uncaught ReferenceError: Promise is not defined

එබැවින් මම අර්ථ දක්වා නොමැති නම් ES3 සඳහා js සම්පාදකයන්ට පහළින් මගේම පොරොන්දු පන්තියක් ක්‍රියාත්මක කිරීමට තීරණය කළෙමි . ඔබගේ ප්‍රධාන කේතයට පෙර මෙම කේතය එක් කර ආරක්ෂිතව පොරොන්දුව භාවිතා කරන්න!

if(typeof Promise === "undefined"){
    function _classCallCheck(instance, Constructor) {
        if (!(instance instanceof Constructor)) { 
            throw new TypeError("Cannot call a class as a function"); 
        }
    }
    var Promise = function () {
        function Promise(main) {
            var _this = this;
            _classCallCheck(this, Promise);
            this.value = undefined;
            this.callbacks = [];
            var resolve = function resolve(resolveValue) {
                _this.value = resolveValue;
                _this.triggerCallbacks();
            };
            var reject = function reject(rejectValue) {
                _this.value = rejectValue;
                _this.triggerCallbacks();
            };
            main(resolve, reject);
        }
        Promise.prototype.then = function then(cb) {
            var _this2 = this;
            var next = new Promise(function (resolve) {
                _this2.callbacks.push(function (x) {
                    return resolve(cb(x));
                });
            });
            return next;
        };
        Promise.prototype.catch = function catch_(cb) {
            var _this2 = this;
            var next = new Promise(function (reject) {
                _this2.callbacks.push(function (x) {
                    return reject(cb(x));
                });
            });
            return next;
        };
        Promise.prototype.triggerCallbacks = function triggerCallbacks() {
            var _this3 = this;
            this.callbacks.forEach(function (cb) {
                cb(_this3.value);
            });
        };
        return Promise;
    }();
}

28

ඇත්ත වශයෙන්ම සමමුහුර්ත ඉල්ලීම, පොරොන්දුව වැනි බොහෝ ප්‍රවේශයන් ඇත, නමුත් මගේ අත්දැකීම් අනුව මම හිතන්නේ ඔබ ඇමතුම් ලබා ගැනීමේ ප්‍රවේශය භාවිතා කළ යුතුය. ජාවාස්ක්‍රිප්ට් හි අසමමුහුර්ත හැසිරීම ස්වාභාවිකය. එබැවින්, ඔබේ කේත ස්නිපටය ටිකක් වෙනස් ලෙස නැවත ලිවිය හැකිය:

function foo() {
    var result;

    $.ajax({
        url: '...',
        success: function(response) {
            myCallback(response);
        }
    });

    return result;
}

function myCallback(response) {
    // Does something.
}

5
කෝල්බැක් හෝ ජාවාස්ක්‍රිප්ට් ගැන සහජයෙන්ම අසමමුහුර්ත කිසිවක් නොමැත.
අළුආන් හඩාඩ්

19

කේතය ඔබ වෙත විසි කරනවා වෙනුවට, JS විසින් ඇමතුම් ලබා ගැනීම සහ අසමමුහුර්තතාව හසුරුවන ආකාරය තේරුම් ගැනීමට ප්‍රධාන සංකල්ප 2 ක් ඇත. (එය වචනයක් ද?)

සිදුවීම් ලූප සහ සමගාමී ආකෘතිය

ඔබ දැනුවත් විය යුතු කරුණු තුනක් තිබේ; පෝලිම්; සිදුවීම් ලූපය සහ තොගය

පුළුල්, සරල වචන වලින්, සිදුවීම් ලූපය ව්‍යාපෘති කළමණාකරුට සමාන ය, එය ක්‍රියාත්මක කිරීමට අවශ්‍ය ඕනෑම කාර්යයකට නිරන්තරයෙන් සවන් දෙන අතර පෝලිම් සහ තොගය අතර සන්නිවේදනය කරයි.

while (queue.waitForMessage()) {
   queue.processNextMessage();
}

යමක් ධාවනය කිරීමට පණිවිඩයක් ලැබුණු පසු එය පෝලිමට එක් කරයි. පෝලිම් යනු ක්‍රියාත්මක කිරීමට බලා සිටින දේවල් ලැයිස්තුවකි (ඔබගේ AJAX ඉල්ලීම වැනි). එය මේ ආකාරයට සිතන්න:

 1. call foo.com/api/bar using foobarFunc
 2. Go perform an infinite loop
 ... and so on

මෙම පණිවිඩ වලින් එකක් ක්‍රියාත්මක කිරීමට යන විට එය පෝලිමේ සිට පණිවිඩය ගෙන තොගයක් සාදයි, පණිවුඩයේ උපදෙස් ක්‍රියාත්මක කිරීම සඳහා ජේඑස් විසින් ක්‍රියාත්මක කළ යුතු සියල්ල වේ. එබැවින් අපගේ උදාහරණයේ දී එය අමතන්නැයි කියනු ලැබේfoobarFunc

function foobarFunc (var) {
  console.log(anotherFunction(var));
}

එබැවින් foobarFunc ක්‍රියාත්මක කිරීමට අවශ්‍ය ඕනෑම දෙයක් (අපගේ නඩුවේදී anotherFunction) තොගයට තල්ලු වේ. ක්‍රියාත්මක කර පසුව අමතක වී ඇත - සිදුවීම් ලූපය පසුව පෝලිමේ ඊළඟ දෙයට ගමන් කරයි (හෝ පණිවිඩවලට සවන් දෙන්න)

මෙහි ඇති ප්‍රධානතම දෙය වන්නේ ක්‍රියාත්මක කිරීමේ අනුපිළිවෙලයි. එනම්

විට ක්‍රියාත්මක වීමට යන දෙයක්

ඔබ බාහිර පාර්ශවයකට AJAX භාවිතා කරමින් ඇමතුමක් ලබා දෙන විට හෝ කිසියම් අසමමුහුර්ත කේතයක් ධාවනය කරන විට (නිදසුනක් ලෙස setTimeout), ඉදිරියට යාමට පෙර ජාවාස්ක්‍රිප්ට් ප්‍රතිචාරයක් මත රඳා පවතී.

විශාල ප්‍රශ්නය වන්නේ එයට ප්‍රතිචාරය ලැබෙන්නේ කවදාද යන්නයි. පිළිතුර අපි නොදනිමු - එබැවින් සිදුවීම් ලූපය එම පණිවිඩය "ඒයි මාව දුවන්න" යැයි පැවසීමට බලා සිටී. ජේඑස් එම පණිවිඩය සමමුහුර්තව බලා සිටියහොත් ඔබේ යෙදුම කැටි වී එය උරා බොනු ඇත. එබැවින් ජේඑස් විසින් පෝලිමේ ඊළඟ අයිතමය ක්‍රියාත්මක කිරීම දිගටම කරගෙන යන අතර පණිවිඩය නැවත පෝලිමට එකතු වන තෙක් බලා සිටී.

අසමමුහුර්ත ක්‍රියාකාරිත්වය සමඟ අපි කෝල්බැක් ලෙස හඳුන්වන දේ භාවිතා කරන්නේ එබැවිනි . එය වචනානුසාරයෙන්ම පොරොන්දුවක් වැනි ය . යම් අවස්ථාවක දී යමක් ආපසු ලබා දීමට මම පොරොන්දු වන පරිදි jQuery විසින් නිශ්චිත ඇමතුම් ලබා ගැනීම deffered.done deffered.failසහ deffered.always(වෙනත් අය අතර) භාවිතා කරයි . ඔබට ඒවා සියල්ලම මෙහි දැකිය හැකිය

එබැවින් ඔබ කළ යුත්තේ යම් අවස්ථාවක දී එය වෙත ලබා දෙන දත්ත සමඟ ක්‍රියාත්මක කිරීමට පොරොන්දු වූ ශ්‍රිතයක් සම්මත කිරීමයි.

කෝල්බැක් ක්ෂණිකව ක්‍රියාත්මක නොවන නමුත් පසුකාලීනව එය ක්‍රියාත්මක නොවූ ශ්‍රිතයට යොමු කිරීම වැදගත් වේ. ඒ නිසා

function foo(bla) {
  console.log(bla)
}

ඒ නිසා බොහෝ විට (නමුත් සෑම විටම නොවේ) ඔබ සමත් fooනොවනු ඇතfoo()

එය යම්කිසි අර්ථයක් ලබා දෙනු ඇතැයි අපේක්ෂා කරමු. ඔබට මේ වගේ දේවල් අවුල් සහගත යැයි හැඟෙන විට - අවම වශයෙන් ඒ පිළිබඳ අවබෝධයක් ලබා ගැනීම සඳහා ප්‍රලේඛනය සම්පූර්ණයෙන්ම කියවීමට මම නිර්දේශ කරමි. එය ඔබව වඩා හොඳ සංවර්ධකයෙකු බවට පත් කරනු ඇත.


18

ES2017 භාවිතා කරමින් ඔබට මෙය ශ්‍රිත ප්‍රකාශය ලෙස තිබිය යුතුය

async function foo() {
    var response = await $.ajax({url: '...'})
    return response;
}

එය මේ ආකාරයට ක්‍රියාත්මක කිරීම.

(async function() {
    try {
        var result = await foo()
        console.log(result)
    } catch (e) {}
})()

නැතහොත් පොරොන්දු වාක්‍ය ඛණ්ඩය

foo().then(response => {
    console.log(response)

}).catch(error => {
    console.log(error)

})

එම දෙවන ශ්‍රිතය නැවත භාවිතා කළ හැකිද?
සුම් දුම්මි

ඔන්කොල්ස්, ලොග් යනුවෙන් හැඳින්වුවහොත් ඔබ ප්‍රති results ල භාවිතා කරන්නේ කෙසේද? සෑම දෙයක්ම එම අවස්ථාවේදී කොන්සෝලය වෙත යන්නේ නැද්ද?
කෙන් ඉන්ග්‍රම්
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.