JQuery: Retornar dados após o sucesso da chamada ajax

Eu tenho algo assim, onde é uma simples chamada para um roteiro que me devolve um valor, um fio.

function testAjax() {
    $.ajax({
      url: "getvalue.php",  
      success: function(data) {
         return data; 
      }
   });
}

mas se eu chamar algo como isto.

var output = testAjax(svar);  // output will be undefined...

então como posso devolver o valor? o código abaixo também não parece funcionar...

function testAjax() {
    $.ajax({
      url: "getvalue.php",  
      success: function(data) {

      }
   });
   return data; 
}

Note: Esta resposta foi escrita em fevereiro de 2010.
Ver atualizações de 2015, 2016 e 2017 na parte inferior.
Você pode'não devolver nada de uma função que seja assíncrona. O que você pode retornar é um promisso. Expliquei como funcionam as promessas em jQuery nas minhas respostas a essas perguntas:

function testAjax() {
  $.ajax({
    url: "getvalue.php",  
    success: function(data) {
      return data; 
    }
  });
}

você pode escrever a sua função testeAjax assim:

function testAjax() {
  return $.ajax({
      url: "getvalue.php"
  });
}

Então podes ter a tua promessa assim:

var promise = testAjax();

Você pode armazenar sua promessa, você pode passá-la, você pode usá-la como argumento em chamadas de função e você pode devolvê-la de funções, mas quando você finalmente quer usar seus dados que são devolvidos pela chamada AJAX, você tem que fazer assim:

promise.success(function (data) {
  alert(data);
});

(Ver actualizações abaixo para uma sintaxe simplificada.) Se os seus dados estiverem disponíveis neste momento, então esta função será imediatamente invocada. Se for't então ela será invocada assim que os dados estiverem disponíveis. O objetivo de fazer tudo isso é que seus dados não estejam disponíveis imediatamente após a chamada para $.ajax porque eles são assíncronos. Promessas é uma boa abstração para funções a dizer: Eu posso'não lhe devolver os dados porque eu não'ainda não os tenho e eu não'não quero bloquear e fazê-lo esperar por isso aqui'é uma prometida em vez disso e você'será capaz de usá-los mais tarde, ou simplesmente dá-lo a outra pessoa e acabar com ele. Veja isto [**DEMO***](http://jsfiddle.net/jW68r/). ATUALIZAÇÃO (2015)

Atualmente (a partir de março de 2015) jQuery Promises não são compatíveis com a especificação Promises/A+, o que significa que podem não cooperar muito bem com outras implementações em conformidade com Promises/A+. Entretanto, jQuery Promises na próxima versão 3.x ** será compatível com a especificação Promises/A+ (graças a Benjamin Gruenbaum por tê-la apontado). Atualmente (a partir de maio de 2015) as versões estáveis de jQuery são 1.x e 2.x.

O que expliquei acima (em março de 2011) é uma forma de usar jQuery Deferred Objects para fazer algo de forma assíncrona que em código síncrono seria alcançado através da devolução de um valor. Mas uma chamada de função síncrona pode fazer duas coisas - ela pode retornar um valor (se puder) ou lançar uma exceção (se puder't retornar um valor). Promises/A+ aborda ambos os casos de uso de uma forma que é tão poderosa quanto o tratamento de exceções em código síncrono. A versão jQuery lida com o equivalente a retornar um valor muito bom, mas o equivalente a um complexo tratamento de exceções é um pouco problemático. Em particular, o ponto completo do tratamento de exceções em código síncrono não é apenas desistir com uma boa mensagem, mas tentar consertar o problema e continuar a execução, ou possivelmente lançar novamente a mesma ou uma exceção diferente para algumas outras partes do programa para tratar. Em código síncrono, você tem uma pilha de chamadas. Em chamadas assíncronas você não't e o tratamento avançado de exceções dentro das suas promessas, como requerido pela especificação Promises/A+, pode realmente ajudá-lo a escrever código que irá tratar de erros e exceções de uma forma significativa, mesmo para casos de uso complexo. Para diferenças entre jQuery e outras implementações, e como converter promessas jQuery para Promessas/A+, veja Vindo de jQuery por Kris Kowal et al. no wiki da biblioteca Q e Promessas chegam em JavaScript por Jake Archibald em HTML5 Rocks.

Como devolver uma promessa real

A função do meu exemplo acima:

function testAjax() {
  return $.ajax({
      url: "getvalue.php"
  });
}

retorna um objeto jqXHR, que é um jQuery Objeto Diferido. Para fazê-lo retornar uma promessa real, você pode mudá-lo para - usando o método do wiki Q:

function testAjax() {
  return Q($.ajax({
      url: "getvalue.php"
  }));
}

ou, usando [o método do artigo HTML5 Rocks] (http://www.html5rocks.com/en/tutorials/es6/promises/#toc-javascript-promises):

function testAjax() {
  return Promise.resolve($.ajax({
      url: "getvalue.php"
  }));
}

Este Promise.resolve($.ajax(...)) é também o que é explicado na documentação do módulo promise e deve funcionar com ES6 Promise.resolve(). Para utilizar o ES6 Promises hoje você pode utilizar [es6-promise module's polyfill()] `](https://github.com/jakearchibald/es6-promise#auto-polyfill) por Jake Archibald. Para ver onde você pode utilizar o ES6 Promises sem o polifill, veja: Posso utilizar: Promises. Para mais informações, veja:

promise.success(function (data) {
  alert(data);
});

você pode escrever:

promise.success(data => alert(data));

ou utilizando a API Promises/A+:

promise.then(data => alert(data));

Lembre-se de usar sempre manipuladores de rejeição com:

promise.then(data => alert(data), error => alert(error));

ou com:

promise.then(data => alert(data)).catch(error => alert(error));

Veja esta resposta para ver por que você deve sempre usar os manipuladores de rejeição com promessas:

promise.then(data => alert("x is " + data.x));

Nem todo navegador suporta essa sintaxe ainda, mas há certos casos em que você'tem certeza de qual navegador seu código será executado - por exemplo, ao escrever uma extensão Chrome, um Firefox Add-on, ou uma aplicação desktop usando Electron, NW.js ou AppJS (veja esta resposta para detalhes). Para o suporte às funções de seta, veja:

  • Há uma sintaxe ainda mais nova neste momento chamada funções async com uma nova palavra-chave `await' que, em vez deste código:
functionReturningPromise()
    .then(data => console.log('Data:', data))
    .catch(error => console.log('Error:', error));

deixa-te escrever:

try {
    let data = await functionReturningPromise();
    console.log('Data:', data);
} catch (error) {
    console.log('Error:', error);
}

Você só pode utilizá-lo dentro de uma função criada com a palavra-chave async. Para mais informações, veja:

Comentários (9)
Solução

A única maneira de retornar os dados da função seria fazer uma chamada síncrona em vez de uma chamada assíncrona, mas isso congelaria o navegador enquanto ele's espera pela resposta.

Você pode passar em uma função de callback que trata do resultado:

function testAjax(handleData) {
  $.ajax({
    url:"getvalue.php",  
    success:function(data) {
      handleData(data); 
    }
  });
}

Chama-lhe assim:

testAjax(function(output){
  // here you use the output
});
// Note: the call won't wait for the result,
// so it will continue with the code here while waiting.
Comentários (7)

Veja o exemplo da Jquery Docs: http://api.jquery.com/jQuery.ajax/ (cerca de 2/3 da página)

Você pode estar à procura do seguinte código:

    $.ajax({
     url: 'ajax/test.html',
     success: function(data) {
     $('.result').html(data);
     alert('Load was performed.');
   }
});

A mesma página...mais para baixo.

Comentários (0)