Kā atgriezt asinhronā izsaukuma atbildi?

Man ir funkcija foo, kas veic Ajax pieprasījumu. Kā es varu atgriezt atbildi no foo?

Es mēģināju atgriezt vērtību no success callback, kā arī piešķirt atbildi vietējam mainīgajam funkcijas iekšienē un atgriezt to, bet neviens no šiem veidiem faktiski neatgriež atbildi.

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`.
Risinājums

→ Vispārīgāku skaidrojumu par asinhronizētu darbību ar dažādiem piemēriem skatīt https://stackoverflow.com/q/23667086/218196

→ Ja problēmu jau saprotat, pārejiet pie tālāk sniegtajiem iespējamiem risinājumiem.

Problēma

Burts A Ajax apzīmē asinhrono . Tas nozīmē, ka pieprasījuma nosūtīšana (vai drīzāk atbildes saņemšana) ir izņemta no parastās izpildes plūsmas. Jūsu piemērā $.ajax atgriežas uzreiz, un nākamais paziņojums return result; tiek izpildīts, pirms vēl tika izsaukta funkcija, kuru jūs nodevāt kā success atgriezenisko zvanu. Lūk, analoģija, kas, cerams, skaidrāk izskaidros atšķirību starp sinhrono un asinhrono plūsmu:

Sinhronā

Iedomājieties, ka jūs piezvanāt draugam un lūdzat viņu kaut ko sameklēt. Lai gan tas var aizņemt kādu laiku, jūs gaidāt pie tālruņa un skatāties telpā, līdz jūsu draugs sniedz jums vajadzīgo atbildi. Tas pats notiek, kad veicat funkcijas izsaukumu, kas satur "normālu" kodu:

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

var item = findItem();

// Do something with item
doSomethingElse();

Lai gan findItem izpilde var aizņemt ilgu laiku, jebkuram kodam, kas nāk pēc var item = findItem();, ir jāgaida, līdz funkcija atgriež rezultātu.

Asinhronā

Jūs atkal izsaucat savu draugu tā paša iemesla dēļ. Bet šoreiz jūs viņam sakāt, ka steidzaties un viņam vajadzētu atzvanīt jums atpakaļ pa mobilo tālruni. Jūs nokārtojat klausuli, izejat no mājas un darāt to, ko bijāt ieplānojis darīt. Kad jūsu draugs jums piezvanīs atpakaļ, jūs nodarbojaties ar informāciju, ko viņš jums nodevis. Tieši tas notiek, kad jūs veicat Ajax pieprasījumu.

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

Tā vietā, lai gaidītu atbildi, izpilde tiek turpināta nekavējoties, un tiek izpildīts paziņojums pēc Ajax izsaukuma. Lai galu galā saņemtu atbildi, jūs sniedzat funkciju, kas jāizsauc pēc atbildes saņemšanas, callback (pamanāt kaut ko? call back ?). Jebkurš paziņojums, kas nāk pēc šī izsaukuma, tiek izpildīts, pirms tiek izsaukts atpakaļsaukums.

Risinājums(-i)

Pieļaujiet JavaScript asinhrono dabu! Lai gan dažas asinhronās operācijas nodrošina sinhronus analogus (tāpat arī "Ajax"), parasti nav ieteicams tās izmantot, īpaši pārlūkprogrammā. Kāpēc tas ir slikti, vai jūs jautājat? JavaScript darbojas pārlūkprogrammas lietotāja saskarnes pavedienā, un jebkurš ilgstoši notiekošs process bloķēs lietotāja saskarni, padarot to neatbilstošu. Turklāt JavaScript izpildes laikam ir noteikts maksimālais izpildes laiks, un pārlūkprogramma jautās lietotājam, vai turpināt izpildi vai nē. Tas viss ir ļoti slikta lietotāja pieredze. Lietotājs nevarēs noteikt, vai viss darbojas pareizi vai nē. Turklāt šis efekts būs vēl sliktāks lietotājiem ar lēnu savienojumu. Turpmāk mēs aplūkosim trīs dažādus risinājumus, kas visi ir uzbūvēti viens uz otra:

  • (ES2017+, pieejams vecākās pārlūkprogrammās, ja izmantojat transpilatoru vai reģeneratoru).
  • Callbacks (populārs mezglā)
  • Solījumi ar then() (ES2015+, pieejami vecākās pārlūkprogrammās, ja izmantojat kādu no daudzajām solījumu bibliotēkām). Visas trīs ir pieejamas pašreizējās pārlūkprogrammās un mezglā 7+.

    ES2017+: Solījumi ar async/await

  1. gadā izdotajā ECMAScript versijā tika ieviests sintakses līmeņa atbalsts asinhronām funkcijām. Ar async un await palīdzību jūs varat rakstīt asinhronās funkcijas "sinhronā stilā". Kods joprojām ir asinhronais, bet tas ir vieglāk lasāms/izprotams. async/await balstās uz solījumiem: async funkcija vienmēr atgriež solījumu. await "izvērš solījumu" un vai nu iegūst vērtību, ar kādu solījums tika atrisināts, vai arī izmet kļūdu, ja solījums tika noraidīts. Svarīgi: Jūs varat izmantot await tikai async funkcijas iekšienē. Pašlaik augstākā līmeņa await vēl nav atbalstīta, tāpēc, lai sāktu async kontekstu, jums, iespējams, būs jāizveido async IIFE (Tūlīt izsauktas funkcijas izteiksme). Vairāk par async un await var izlasīt MDN. Šeit ir piemērs, kas balstās uz iepriekš minēto kavēšanos:
// 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);
})();

Pašreizējās pārlūkprogrammas un mezgla versijas atbalsta async/await. Varat atbalstīt arī vecākas vides, pārveidojot savu kodu uz ES5 ar reģeneratora palīdzību (vai rīkiem, kas izmanto reģeneratoru, piemēram, Babel).

Ļaujiet funkcijām pieņemt callbacks

Atgriezeniskais zvans ir vienkārši funkcija, kas nodota citai funkcijai. Šī cita funkcija var izsaukt nodoto funkciju, kad vien tā ir gatava. Asinhronā procesa kontekstā atgriezeniskais izsaukums tiks izsaukts, kad vien asinhronais process būs pabeigts. Parasti atpakaļsaukumam parasti tiek nodots rezultāts. Jautājuma piemērā jūs varat likt foo pieņemt atpakaļsaukumu un izmantot to kā success atpakaļsaukumu. Tātad šis

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

kļūst par

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

Šeit mēs definējām funkciju "inline", bet jūs varat nodot jebkuras funkcijas atsauci:

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

foo(myCallback);

Pati foo ir definēta šādi:

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

callback atsaucas uz funkciju, ko mēs nododam foo, kad to izsaucam, un mēs to vienkārši nododam tālāk success. T.i., kad Ajax pieprasījums būs veiksmīgs, $.ajax izsauks callback un nodos atbildi atpakaļsaukumam (uz kuru var atsaukties ar result, jo tieši tā mēs definējām atpakaļsaukumu). Jūs varat arī apstrādāt atbildi pirms tās nodošanas atpakaļsaukumam:

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

Kodu rakstīt, izmantojot atgriezeniskos izsaukumus, ir vienkāršāk, nekā varētu šķist. Galu galā JavaScript pārlūkprogrammā ir lielā mērā orientēts uz notikumiem (DOM notikumiem). Ajax atbildes saņemšana nav nekas cits kā notikums.
Grūtības var rasties, ja jāstrādā ar trešo pušu kodu, taču lielāko daļu problēmu var atrisināt, vienkārši pārdomājot lietojumprogrammas plūsmu.

ES2015+: then(): solījumi ar then()

Promise API ir jauna ECMAScript 6 (ES2015) funkcija, taču tai jau ir labs pārlūkprogrammas atbalsts. Ir arī daudzas bibliotēkas, kas implementē standarta Promises API un nodrošina papildu metodes, lai atvieglotu asinhrono funkciju izmantošanu un veidošanu (piemēram, bluebird). Promises ir konteineri nākotnes vērtībām. Kad solījums saņem vērtību (tā ir atrisināta) vai kad tas tiek atcelts (atteikts), tas informē visus savus "klausītājus", kuri vēlas piekļūt šai vērtībai. Priekšrocība salīdzinājumā ar parastajiem atpakaļsaukumiem ir tā, ka tie ļauj atdalīt kodu un tos ir vieglāk veidot. Šeit ir vienkāršs solījuma izmantošanas piemērs:

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

Piemērojot mūsu Ajax izsaukumam, mēs varētu izmantot šādus solījumus:

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

Visu solījumu piedāvāto priekšrocību aprakstīšana pārsniedz šīs atbildes apjomu, taču, ja rakstāt jaunu kodu, jums vajadzētu nopietni apsvērt to izmantošanu. Tie nodrošina lielisku abstrakciju un jūsu koda atdalīšanu. Vairāk informācijas par solījumiem: HTML5 rocks - JavaScript Promises.

Piebilde: jQuery's atliktie objekti

Deferred objects ir jQuery's pielāgota solījumu implementācija (pirms solījumu API tika standartizēts). Tie uzvedas gandrīz tāpat kā solījumi, bet piedāvā nedaudz atšķirīgu API. Katra jQuery Ajax metode jau atgriež "atlikto objektu" (patiesībā atliktā objekta solījumu), ko jūs varat vienkārši atgriezt no savas funkcijas:

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

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

Piebilde: Promise gotchas

Paturiet prātā, ka solījumi un atliktie objekti ir tikai konteineri nākotnes vērtībai, tie nav pati vērtība. Piemēram, pieņemsim, ka jums ir šādi:

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
}

Šis kods nepareizi saprot iepriekš minētās asinhronitātes problēmas. Konkrēti, $.ajax() neaptur kodu, kamēr tas pārbauda '/password' lapu jūsu serverī - tas nosūta pieprasījumu uz serveri un, kamēr tas gaida, nekavējoties atgriež jQuery Ajax Deferred objektu, nevis atbildi no servera. Tas nozīmē, ka if paziņojums vienmēr saņems šo Deferred objektu, uzskatīs to par true un turpinās darbu tā, it kā lietotājs būtu pieteicies. Tas nav labi. Bet labojums ir vienkāršs:

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

Nav ieteicams: Sinhronie "Ajax" izsaukumi

Kā jau minēju, dažām(!) asinhronajām operācijām ir sinhroni ekvivalenti. Es neatbalstu to lietošanu, bet pilnīguma labad šeit ir norādīts, kā jūs varētu veikt sinhrono izsaukumu:

Bez jQuery

Ja jūs tieši izmantojat XMLHTTPRequest objektu, kā trešo argumentu .open nododiet false.

jQuery

Ja izmantojat jQuery, varat iestatīt async opciju uz false. Ņemiet vērā, ka šī opcija ir atcelta kopš jQuery 1.8. Tad jūs varat izmantot success izsaukumu vai piekļūt jqXHR objekta responseText īpašībai:

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

Ja izmantojat jebkuru citu jQuery Ajax metodi, piemēram, $.get, $.getJSON u.c., jums tā jāmaina uz $.ajax (jo $.ajax var nodot tikai konfigurācijas parametrus). Atgādinām! Nav iespējams veikt sinhrono JSONP pieprasījumu. JSONP pēc savas būtības vienmēr ir asinhronais (vēl viens iemesls, kāpēc pat neapsvērt šo iespēju).

Komentāri (35)

Ja jūs neizmantojat jQuery savā kodā, šī atbilde ir domāta jums.

Jūsu kodam vajadzētu būt apmēram šādam:

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

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

Felix Kling paveica lielisku darbu, rakstot atbildi cilvēkiem, kas izmanto jQuery AJAX, es nolēmu piedāvāt alternatīvu tiem, kas to nedara.

(Piezīme, tiem, kas izmanto jauno fetch API, Angular vai promises, esmu pievienojis citu atbildi zemāk).


Kas jums'ir jārisina

Šis ir īss kopsavilkums "Problēmas skaidrojums" no citas atbildes, ja pēc šīs izlasīšanas neesat pārliecināts, izlasiet to.

AJAX A apzīmē asinhrono. Tas nozīmē, ka pieprasījuma nosūtīšana (vai drīzāk atbildes saņemšana) tiek izņemta no parastās izpildes plūsmas. Jūsu piemērā .send atgriežas uzreiz, un nākamais paziņojums return result; tiek izpildīts, pirms vēl tika izsaukta funkcija, kuru jūs nodevāt kā success izsaukumu.

Tas nozīmē, ka atgriešanās brīdī jūsu definētais klausītājs vēl nav izpildīts, un tas nozīmē, ka vērtība, kuru jūs atgriežat, vēl nav definēta.

Šeit ir vienkārša analoģija

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

[(Fiddle)][2]

Atgrieztā a vērtība ir nedefinēta, jo a=5 daļa vēl nav izpildīta. AJAX darbojas šādi - jūs atdodat vērtību, pirms serveris ir paspējis paziņot pārlūkprogrammai, kāda ir šī vērtība.

Viens no iespējamiem šīs problēmas risinājumiem ir kodēt reaktīvi , norādot programmai, ko darīt, kad aprēķins ir pabeigts.

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

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

To sauc par CPS. Būtībā mēs nododam getFive darbību, kas jāveic, kad tā tiek pabeigta, un mēs sakām savam kodam, kā reaģēt, kad notikums ir pabeigts (piemēram, mūsu AJAX izsaukums vai, šajā gadījumā, laika limits).

Lietošana būtu šāda:

getFive(onComplete);

Kādam ekrānā jāparādās brīdinājumam "5". [(Fiddle)][4].

Iespējamie risinājumi

Pamatā ir divi veidi, kā to atrisināt:

  1. Padarīt AJAX izsaukumu sinhronu (sauksim to par SJAX).
  2. Pārstrukturējiet savu kodu, lai tas pareizi darbotos ar atpakaļsaukumiem.

1. Sinhronais AJAX - nedariet tā!!

Kas attiecas uz sinhrono AJAX, nevajag to darīt! Felix's atbildē ir minēti daži pārliecinoši argumenti, kāpēc tā ir slikta ideja. Rezumējot, tas iesaldēs lietotāja pārlūkprogrammu, līdz serveris atgriezīs atbildi, un radīs ļoti sliktu pieredzi lietotājam. Šeit ir vēl viens īss kopsavilkums no MDN par to, kāpēc:

XMLHttpRequest atbalsta gan sinhrono, gan asinhrono komunikāciju. Tomēr kopumā veiktspējas apsvērumu dēļ priekšroka jādod asinhroniem pieprasījumiem, nevis sinhroniem pieprasījumiem.

Īsāk sakot, sinhronie pieprasījumi bloķē koda izpildi... ...tas var radīt nopietnas problēmas...

Ja jums tas ir jādara, varat izmantot karodziņu: Lūk, kā:

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. Pārstrukturēt kodu

Ļaujiet savai funkcijai pieņemt atpakaļsaukumu. Piemērā redzamajā kodā foo var izveidot funkciju, kas pieņem atpakaļsaukumu. Mēs savam kodam norādīsim, kā reaģēt, kad foo būs pabeigts.

Tātad:

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

Kļūst:

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

Šeit mēs nodevuši anonīmu funkciju, bet tikpat labi mēs varētu nodot arī atsauci uz jau esošu funkciju, tādējādi tas izskatās šādi:

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

Sīkāku informāciju par to, kā tiek veidots šāds atgriezenisko zvanu dizains, atradīsiet Felix'ā atbildē.

Tagad definēsim foo, lai pats attiecīgi rīkotos

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

[(fiddle)][6]

Tagad mēs esam padarījuši mūsu foo funkciju par darbību, kas tiek izpildīta, kad AJAX ir veiksmīgi pabeigts, mēs varam to paplašināt, pārbaudot, vai atbildes statuss nav 200, un attiecīgi rīkoties (izveidot fail handler u.c.). Tas efektīvi atrisina mūsu problēmu.

Ja jums joprojām ir grūti to saprast izlasiet AJAX sākumposma rokasgrāmatu MDN.

Komentāri (4)

XMLHttpRequest 2 (vispirms izlasiet Benjamin Gruenbaum & amp; Felix Kling atbildes). Ja neizmantojat jQuery un vēlaties jauku, īsu XMLHttpRequest 2, kas darbojas modernās pārlūkprogrammās un arī mobilajās pārlūkprogrammās, iesaku to izmantot šādā veidā:

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

Kā redzat:

  1. Tā ir īsāka nekā visas pārējās uzskaitītās funkcijas.
  2. Atgriezeniskais zvans tiek iestatīts tieši (tāpēc nav lieku nevajadzīgu slēgšanu).
  3. Tā izmanto jauno onload (tāpēc jums nav jāpārbauda readystate && statuss).
  4. Ir vēl dažas citas situācijas, kuras es neatceros, kas padara XMLHttpRequest 1 kaitinošu. Ir divi veidi, kā iegūt šā Ajax izsaukuma atbildi (trīs, izmantojot XMLHttpRequest var nosaukumu): Vienkāršākais:
this.response

Vai arī, ja kāda iemesla dēļ jūs pievienojat() izsaukumu kādai klasei:

e.target.response

Piemērs:

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

Vai (iepriekš minētais ir labāks, anonīmās funkcijas vienmēr ir problēma):

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

Nekas vienkāršāks. Tagad daži cilvēki droši vien teiks, ka labāk izmantot onreadystatechange vai pat XMLHttpRequest mainīgo nosaukumu. Tas ir nepareizi. Skatiet XMLHttpRequest uzlabotās funkcijas. Tas atbalsta visas *modernās pārlūkprogrammas. Un es to varu apstiprināt, jo izmantoju šo pieeju kopš XMLHttpRequest 2. Man nekad nav bijušas nekāda veida problēmas visās pārlūkprogrammās, ko es izmantoju. onreadystatechange ir noderīgs tikai tad, ja vēlaties saņemt galvenes 2. stāvoklī. Mainīgā XMLHttpRequest nosaukuma izmantošana ir vēl viena liela kļūda, jo jums ir jāizpilda atpakaļsaukums onload/oreadystatechange slēgumos, citādi jūs to zaudējat.

Ja vēlaties kaut ko sarežģītāku, izmantojot post un FormData, varat viegli paplašināt šo funkciju:

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

Atkal ... tā ir ļoti īsa funkcija, bet tā iegūst & amp; post. Lietošanas piemēri:

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

Vai nodot pilnu veidlapas elementu (document.getElementsByTagName('form')[0]):

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

Vai arī iestatiet dažas pielāgotas vērtības:

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

Kā redzat, es neīstenoju sinhronizāciju... tas ir slikti. Ņemot to vērā... kāpēc to nedarīt vienkāršāk?

Kā minēts komentārā, kļūdas && sinhronā izmantošana pilnībā izjauc atbildes jēgu. Kurš ir jauks īss veids, kā izmantot Ajax pareizā veidā? Kļūdu apstrādātājs

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

Iepriekš minētajā skripta gadījumā jums ir kļūdas apstrādātājs, kas ir statiski definēts, tāpēc tas neapdraud funkciju. Kļūdu apstrādātāju var izmantot arī citām funkcijām. Bet, lai patiešām izsauktu kļūdu, vienīgais veids ir uzrakstīt nepareizu URL, un tādā gadījumā katra pārlūkprogramma izmet kļūdu. Kļūdu apstrādātāji varbūt ir noderīgi, ja iestatāt pielāgotas galvenes, iestatāt responseType uz blob array buferi vai ko citu... Pat tad, ja kā metodi nododat 'POSTAPAPAP', kļūda netiks izmesta. Pat tad, ja kā formdata tiks nodoti 'fdggdgilfdghfldj', kļūda netiks pieļauta. Pirmajā gadījumā kļūda ir displayAjax() iekšpusē zem this.statusTextMetode nav atļauta. Otrajā gadījumā tas vienkārši darbojas. Jums jāpārbauda servera pusē, vai esat nodevis pareizos amata datus. Ja starpdomēna nav atļauta, automātiski tiek izmesta kļūda. Kļūdas atbildē nav kļūdu kodu. Ir tikai this.type, kas ir iestatīts uz kļūdu. Kāpēc pievienot kļūdu apstrādātāju, ja jums nav pilnīgas kontroles pār kļūdām? Lielākā daļa kļūdu tiek atgrieztas iekšpusē šajā atpakaļsaukuma funkcijā displayAjax(). Tātad: Ja spējat pareizi nokopēt un ielīmēt URL adresi, tad kļūdu pārbaude nav nepieciešama. ;) PS: Kā pirmo testu es uzrakstīju x('x', displayAjax)..., un tas pilnīgi saņēma atbildi...??????? Tad es pārbaudīju mapi, kurā atrodas HTML, un tur bija fails ar nosaukumu 'x.xml'. Tātad, pat ja jūs aizmirsāt faila paplašinājumu, XMLHttpRequest 2 to atradīs. Es LOL'd

Sinhronizēta faila lasīšana Tā nedariet. Ja vēlaties uz brīdi bloķēt pārlūkprogrammu, ielādējiet labu lielu .txt failu sinhronizēti.

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

Tagad jūs varat veikt

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

Nav cita veida, kā to izdarīt neasinhroni. (Jā, ar setTimeout cilpu... bet nopietni?) Ja jūs strādājat ar API vai tikai ar saviem saraksta failiem, vai ar ko citu, jūs vienmēr izmantojat dažādas funkcijas katram pieprasījumam... Tikai tad, ja jums ir lapa, kurā vienmēr ielādējat vienu un to pašu XML/JSON vai ko citu, jums ir vajadzīga tikai viena funkcija. Tādā gadījumā nedaudz modificējiet Ajax funkciju un aizstāt b ar savu īpašo funkciju.

Iepriekš minētās funkcijas ir paredzētas pamata lietošanai. Ja vēlaties paplašināt funkciju... Jā, varat. Es'izmantoju daudz API, un viena no pirmajām funkcijām, ko integrēju katrā HTML lapā, ir pirmā Ajax funkcija šajā atbildē, tikai ar GET... Bet ar XMLHttpRequest 2 var izdarīt daudz ko: Es veicu lejupielādes pārvaldnieks (izmantojot diapazonus abās pusēs ar atsākšanu, filereader, failu sistēma), dažādi attēlu izmēru pārveidotāji, izmantojot audekls, aizpildīt web SQL datu bāzes ar base64images un daudz ko citu... Bet šajos gadījumos jums vajadzētu izveidot funkciju tikai šim nolūkam... dažreiz jums ir nepieciešams blob, masīva buferi, jūs varat iestatīt galvenes, override mimetype un ir daudz vairāk... Bet jautājums ir par to, kā atgriezt Ajax atbildi... (Es pievienoju vienkāršu veidu.)

Komentāri (7)