« 1 2 »
Autor Zpráva
quatzael
Profil
Mám níže uvedenou ajaxovou funkci. Potřebuju, aby ta funkce házela buď true nebo false, protože jí mám potom v podmínce if.

problém je, že nějak pořád celkově vrací hodnotu false.. Vypadá to, že ajax proběhne ok, vrátí hodnotu true, jenže než jí ta celá funkce stačí vrátit (protože nečeká na odpověď ze serveru), tak nějak pořád vrací false..

function ajax(value)
 {
 $.ajaxSetup({
    'beforeSend' : function(xhr) {
    xhr.overrideMimeType('text/html; charset=UTF-8');
    }
  });
$.ajax({
url: "/php/ajax.php",    
type: "POST",        
data: {val: value},          
success: function (answer) {  
   if (answer == true)
   return true;   
   else
   return false;
   },
error: function() {
return false;}   
   });
}

if (ajax("abc"))
window.alert("ok");
Tori
Profil
A co je smyslem? Pokud chcete provést nějakou akci po dokončení ajaxu, tak by bylo jednodušší tu akci zabalit do funkce a tu zavolat v success callbacku.
quatzael
Profil
Tori:
php script vyhodí buď hodnotu true nebo false (samozřejmě na základě vstupní proměnné). A já potřebuju, aby ta celá javascriptová funkce vyplivla true pokud php script vrátí true. Pokud se stane cokoli jiného (např php vyhodí false nebo ten php script nebude vůbec fungovat nebo tak něco) tak to má vyhodit false..
Tak, aby se to dalo použít v podmínce if jak je úplně dole.

Teď to vypadá, že se to chová tak, že php script vrátí true, ale celá js funkce se v podmínce chová jako false..
yFang
Profil
quatzael:
Ona ta funkce ajax nevrací false, ale undefined (žádný return v ní není, tak ani nic jiného vracet nemůže). To, co se děje v anonymní funkci, která je u success, nijak neovlivní návratovou hodnotu funkce ajax.

Takto to obecně řešit nelze. Je potřeba zavolat nějaký callback potom, co se vrátí nějaká odpověď ze serveru.
quatzael
Profil
yFang:
A jak se teda volá ten callback? Nikdy jsem na to nepřišel..
yFang
Profil
quatzael:
Místo toho, abys něco vracel z té anonymní funkce, tak tam provedeš to, co chceš udělat. Například pokud chceš něco zobrazit, když ti to vrátí true, tak to uděláš tam nebo zavoláš funkci, která to udělá. Záleží, čeho chceš docílit.

Ještě si dej pozor na tu podmínku. Nevím, co vracíš ze serveru, ale jestli pouze string true/false, tak ti ta podmínka, tak jak je, nebude fungovat správně, protože se ti v podmínce oba stringy přetypují na true, protože nejsou prázdné.
quatzael
Profil
yFang:
Například pokud chceš něco zobrazit, když ti to vrátí true, tak to uděláš tam nebo zavoláš funkci, která to udělá.
To sice v tomto případě chci. Ale zároveň tu funkci chci používat i pro jiné "akce", takže mít jí několikrát napsanou s tím, že se tam bude měnit jen ta část v tom success mi připadá dost zbytečný..

tak to uděláš tam nebo zavoláš funkci, která to udělá.
A nejde tam nějak zavolat anonymní (nevím jak se jim správně říká) funkci, která to tam přímo vykoná, abych ji nemusel definovat někde před tím?

Nevím, co vracíš ze serveru
Z toho serveru vracím přímo true nebo false. Čili tam mám:
echo true; resp. echo false;

Je pravda, že pak by asi ta podmínka v tý části success měla nejspíš vypadat takto, ne?
if (answer === true)



Ještě by to asi šlo takhle:

function ajax(value)
 { var check = false;
 $.ajaxSetup({
    'beforeSend' : function(xhr) {
    xhr.overrideMimeType('text/html; charset=UTF-8');
    }
  });
$.ajax({
url: "/php/ajax.php",    
type: "POST",        
data: {val: value},          
success: function (answer) {  
   if (answer == true)
   check = true;
   } 
   });
   return check;
}
 
if (ajax("abc"))
window.alert("ok");


Ale jak mám docílit toho aby ta funkce s tím příkazem return check; počkala až se dokončí ajax?
yFang
Profil
quatzael:
To sice v tomto případě chci. Ale zároveň tu funkci chci používat i pro jiné "akce", takže mít jí několikrát napsanou s tím, že se tam bude měnit jen ta část v tom success mi připadá dost zbytečný..
To určité zbytečné je, stačí si do funkce předat funkci, která se má zavolat.

A nejde tam nějak zavolat anonymní (nevím jak se jim správně říká) funkci, která to tam přímo vykoná, abych ji nemusel definovat někde před tím?
Ano, to je taky možnost.

Je pravda, že pak by asi ta podmínka v tý části success měla nejspíš vypadat takto, ne?
if (answer === true)
To ne, to bys provnával string s boolem a to by určitě neprošlo, spíš to potřebuješ porovnat se stringem.


Můžeš to zkusit upravit třeba nějak takhle:
function ajax(value, callback) {

    $.ajax({
        url: "/php/ajax.php",    
        type: "POST",        
        data: {val: value},          
        success: function (answer) {  
            if (answer === 'true') {
                callback();
            }
        } 
    });

}
 
ajax('abc', function(){
    window.alert("ok");
});
quatzael
Profil
yFang:
No jo, jenže já nevím jak to funguje. Ten callback jako funkce musí někde definovaná? A co mám konkrétně dát jako parametr místo toho slova callback?
yFang
Profil
quatzael:
Podívej se dolů do toho kódu, je tam volání té funkce ajax, callback je funkce, která může být klidně anonymní.
juriad
Profil
quatzael:
Vždy, když pracuješ s AJAXem nebo obecně čímkoli asynchronním, tak si představ, že odpověď serveru může trvat klidně minutu nebo také nemusí dorazit nikdy. Co by se asi stalo, pokud by ta tvá funkce čekala na odpověď?
Nutně by musel zamrznout celý prohlížeč, protože pohyb myší, stisk na klávesnici, cokoli může způsobit další JavaScriptové události. Ale JavaScript v prohlížeči je jednovláknový; všechny události se zpracovávají postupně.

To je důvod, proč se používá asynchronní volání. To funguje takto: Vypůjčíš si nějaký objekt AJAX, který je v jistém smyslu speciální a patří prohlížeči.
Ty mu nastavíš adresu a funkcí send ho předáš prohlížeči, který se postará o jeho vykonání.
Pokud nastavíš i vlastnosti success a error, tak prohlížeč tyto funkce zavolá v okamžiku, kdy to bude vhodné. Jakmile nepoběží žádný tvůj skript a prohlížeč se dozví stav požadavku ze serveru.
Je v celku jedno, jak to volání vypadá; zápis z jQuery je jen obal, který to umožňuje napsat na jediný řádek. Princip se však neliší.

// pseudokód
function onclick() { // když uživatel klikne na tlačítko
  var ajax = new AJAX(); // milý prohlížeči, chci po tobě něco poslat na server
  ajax.url = "..."; // bude to tato adresa
  ajax.success = function() { ... }; // až dostaneš kladnou odpověď, prosím zavolej tuto funkci
  ajax.error = function() { ... }; // ale pokud dojde k nějaké chybě, zavolej raději tuto funkci
  ajax.send(); // víc po tobě nechci, můžeš jednat

  nějakýDlouhýVýpočet(); // zatímco běží tato funkce, success ani error se nezavolají
}

Uvědom si, že něco podobného je funkce setTimeout - také prohlížeči říkáš: zavolej mi tuto funkci ve správný čas. Pokud nastavíš, aby se funkce zavolala za 100 ms, ale tvůj prohíhající výpočet trvá třeba sekundu, tak se zavolá až ten výpočet skončí.
Když budeš považovat funkci/metodu/objekt ajax za takový pokročilý setTimeout, začne ti být jasné, že nemá smysl, čekat na výsledek.
Tori
Profil
quatzael:
A já potřebuju, aby ta celá javascriptová funkce vyplivla true pokud php script vrátí true. Pokud se stane cokoli jiného (např php vyhodí false nebo ten php script nebude vůbec fungovat nebo tak něco) tak to má vyhodit false..
Pokud by nevadilo posílat data přes GET, tak by možná bylo jednodušší pingnout server. Ale v případě pomalé reakce serveru bude skript čekat, nevím jestli to vadí nebo ne.
Radek9
Profil
quatzael:
Ten callback je vlastně ta funkce success. Cokoli provedeš nebo zavoláš v ní se děje asynchronně. Myslím, že celý problém tkví v tom, že vlastně nechápeš, co to je. Asynchronní funkce se volají vždy až po dokončení aktuálního synchronního stacku.

console.log("a");

runAsync(function callback() {
  console.log("b");
});

console.log("c");

Začátečník by pravděpodobně předpokládal, že script vypíše a, b, c, ve skutečnosti ale vypíše a, c a až za chvíli (podle doby trvání asynchronní akce) vypíše b. Tím pádem asi už i jistě chápeš, že callback asynchronní akce nemůže nic vracet. Script na ni nikde nečeká, pouze se po jejím dokončení vytvoří událost. Máš tedy několik možností, jak s podobnou situací naložit:

1) V callbacku zavolat další funkci, která bude pracovat s daty ze serveru:
var anotherCallback = function (answer) {
  …
};

$.ajax({
  url: "/php/ajax.php",
  type: "POST",
  data: { val: value },
  success: function (answer) {
    if (answer == true) {
      anotherCallback(answer);
    }
  }
});

2) Využít promise-pattern (v jQuery Deferred):

function ajax() {
  return $.ajax({
    url: "/php/ajax.php",
    type: "POST",
    data: { val: value }
  });
}

ajax().then(function (answer) {
  …
});

3) Můžeš využít funkcionalitu nejnovějších prohlížečů a použít generátory a knihovnu Q k vytvoření jakési async/await struktury:
Q.async(function* () {
  var answer = yield ajax();
  
  alert(answer);
});

Třetí možnost je sice nejhezčí, bohužel však většinou (kvůli nepodpoře) nefunkční, takže ji zatím nedoporučuji používat.
quatzael
Profil
yFang:
Podívej se dolů do toho kódu, je tam volání té funkce ajax
Sorry, díval jsem se, ale špatně. Teď to vidím.

juriad, Radek9:
Myslím, že celý problém tkví v tom, že vlastně nechápeš, co to je. Asynchronní funkce se volají vždy až po dokončení aktuálního synchronního stacku.
Já vím co to je asynchronnost. Proto jsem to vlákno taky podle toho nazval, že ten problém s tou asynchronností potřebuju vyřešit.

Tori:
Pokud by nevadilo posílat data přes GET, tak by možná bylo jednodušší pingnout server. Ale v případě pomalé reakce serveru bude skript čekat, nevím jestli to vadí nebo ne.
To by znamenalo, že by se ten celý script opravdu zastavil a čekal na odpověď?

No je pravda, že to budu muset vyřešit nějak, aby se čekalo na odpověď serveru, protože jde zhruba o tohle:

Dělám kontrolu formuláře před odesláním. Tzn. všechno je to ve funkci submit:
$("#form").submit(function(){ ... });

Kontroluju jednotlivý položky a když jsou ok, tak je přidávám do pole ověřených položek.
A pak v cyklu for projedu pole povinných položek a porovnám jestli každá jednotlivá položka taky nachází v poli těch ověřených.

Tzn. že bych potřeboval, aby stejně i před tou finální kontrolou přes ten cyklus for celý ten script počkal až se dokončí ten ajax.
Radek9
Profil
Tori, quatzael:
Ale v případě pomalé reakce serveru bude skript čekat, nevím jestli to vadí nebo ne.
To by znamenalo, že by se ten celý script opravdu zastavil a čekal na odpověď?
Mám pocit, že obrázky se taky načítají asynchronně. Mají k tomu příslušné událost, onload a onerror.

quatzael:
Proto jsem to vlákno taky podle toho nazval, že ten problém s tou asynchronností potřebuju vyřešit.
Potom použij jedno z řešení, které jsem zaslal. Žádné jiné řešení neexistuje.

Tzn. že bych potřeboval, aby stejně i před tou finální kontrolou přes ten cyklus for celý ten script počkal až se dokončí ten ajax.
To se ale dělá úplně jinak. Zruš defaultní akci (pomocí e.preventDefault() nebo return false;), pošli requesty a potom, pokud vrátí správný výsledek, znovu submitni formulář.
quatzael
Profil
Radek9:
pošli requesty a potom, pokud vrátí správný výsledek, znovu submitni formulář.
Jenže já tam těch ajaxů budu mít víc. Jak mám udělat fakticky to, abych ten příkaz, který submituje formulář, se odehrál až poté co se ukončí všechny ajaxy?
Radek9
Profil
quatzael:
api.jquery.com/jquery.when
juriad
Profil
quatzael:
A proč nemůže být jeden (pošleš pole požadavků) a na serveru si to pole rozebereš a po částech zpracuješ a vrátíš pole odpovědí?
quatzael
Profil
juriad:
To bych sice mohl nějak udělat dát to všechno do jednoho ajaxu, ale tím, že každou funkci používám i zvlášť, tak bych tam musel mít další funkci navíc.. což by snad nebylo úplně ten největší problém..

Radek9:
api.jquery.com/jquery.when
To se zdá jako to správný řešení, který hledám.. Akorát mi není úplně jasný jak to přesně funguje. Musím tam dávat přímo ty ajaxy nebo i normální funkce, které mají ajax uvnitř?
Radek9
Profil
quatzael:
Tam jde o výsledek té jQuery funkce ajax. Vrací totiž speciální objekt Deferred. Takže pokud z té tvé vlastní funkce nakonec vrátíš ten stejný výsledek, tak je to celkem jedno.
quatzael
Profil
Radek9:
No tak to samotný řešení s when vypadá opravdu ok, jenom je pořád problém s tím, že ta ajaxová funkce nevyhodí hodnotu true i přesto, že se callback funkce zavolá.. Vyplivne to undefined.

function ajax(value, callback) {
 
    $.ajax({
        url: "/php/ajax.php",    
        type: "POST",        
        data: {val: value},          
        success: function (answer) {  
            if (answer === 'true') {
                callback(answer); // podmínka je splněna a funkce callback opravdu proběhne
            }
        } 
    });
 
}
 
ajax('abc', function(answer){
   return answer;
   });
CZechBoY
Profil
Co takhle kouknout občas do dokumentace a vyčíst si, že hned 2. parametr (podle abecedy) se jmenuje async, což shodou náhod zrovna tobě by mohlo pomoci.

Nečetl jsem celou diskusi, takže nevím co konkrétně řešíš...
quatzael
Profil
CZechBoY:
Nečetl jsem celou diskusi, takže nevím co konkrétně řešíš...
Co jsem nečetl, tak mi to teda prosímtě řekni.. Celý to mám samozřejmě takhle, s tím, že ajax1 a ajax2 jsou funkce prakticky jako výše definovaný ajax.
Prostě se snažím tady vysvětlit, že je problém v tom, že i přesto, že se zavolá ta callback funkce, tak to celkově vyhodí undefined přestože má proměnná answer hodnotu "true"

$.when( ajax1(val, function(answer){ return answer;}), ajax2(val2, function(answer){ return answer;}) ).done(function( a1, a2) {
window.alert(a1); // napíše "undefined"
window.alert(a2); // napíše "undefined"
});
CZechBoY
Profil
quatzael:
Umíš česky? Psal jsem "Nečetl jsem" - to znamená první osoba - já. Dál tě nehodlám učit česky :-)

Zkoušel si tam hodit to nastavení

$.ajax({
async: false,
url: fsdfdsfds
});
?

Další volání bys musel mít v tom callbacku a ne jít zase dál ve skriptu.
quatzael
Profil
CZechBoY:
Sorry, už jsem z toho tak zoufalej, že jsem nějak viděl tu 2. osobu. Doporučení typu "přečti si znovu vlákno" tady dostávám celkem často (i když to často k ničemu nevede), takže jsem nějak automaticky předjímal podobné doporučení..:o)


async: false, jsem teď zkusil, a to sice proběhne, ale zase to nefunguje s tou funkcí when zřejmě..
Radek9
Profil
quatzael:
Tak znovu. Při řešení s Deferred se napracuje s callbacky, ale s promise rozhraním:

function ajax(value) {
  return $.ajax({
    url: "/php/ajax.php",
    type: "POST",
    data: { val: value }
  });
}

$.when(ajax(value1), ajax(value2)).then(function (result1, result2) {
  alert(result1);
  alert(result2);
});

CZechBoY:
Neraď něco, o čem vůbec nic nevíš. Synchronní requesty jsou zabiják pro prohlížeč. Po dobu jejich trvání je jakákoli jiná akce zablokovaná a stránka tedy na nic neodpovídá.
quatzael
Profil
Respektive to async: false, má na svědomí to, že to celý nějak neproběhne (ta callback funkce jo, ale ne ta celá submitovací funkce)
CZechBoY
Profil
quatzael:
Dobrá, známe :D

Zkoušel si to nastavení async: false?
Vezmu-li tvůj kód z úvodního příspěvku a upravím do funkční podoby:
function ajax(value)
{
  $.ajaxSetup({
    'beforeSend' : function(xhr) {
      xhr.overrideMimeType('text/html; charset=UTF-8');
    }
  });
  var ret = false; // pridano
  $.ajax({
    async: false, // pridano
    url: "./",
    type: "POST",
    data: {val: value},
    success: function (answer) {
      if (answer == 'true')
        ret = true;
      else
        ret = false;
    },
    error: function() {
      ret = false;
    }
  });

  return ret; // vracime promennou
}
Nemůžeš vracet returnem v callbacku... to bys vrátil zpátky do jquery funkce ajaxu - k ničemu.


Radek9:
On chce synchronní dotaz, nebo ne?
Já psal ať to hodí celý do callbacku, pak to bude probíhat asynchronně.
Proti lepšímu řešení nic nemám :-)
quatzael
Profil
Radek9:
No, mě to s těma callbackama teď fungovalo, bez nich to nefunguje..:o(
CZechBoY
Profil
quatzael:
Jj, tak je použij, je to lepší řešení.
« 1 2 »

Vaše odpověď

Mohlo by se hodit

Neumíte-li správně určit příčinu chyby, vkládejte odkazy na živé ukázky.
Užíváte-li nějakou cizí knihovnu, ukažte odpovídajícím, kde jste ji vzali.

Užitečné odkazy:

Odkud se sem odkazuje


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: