Why does this function not return values

Asked

Viewed 290 times

2

I am doing a more generic function to perform AJAX calls, in which I put the URL that should be searched and the data that it should send, and I wait as return the loaded data.

However, I’m not succeeding, since within the function if I give a console.log it shows the data, but when the function returns the data when I use it returns undefined. What could be?

let amigos = retornaInformacoes('/amigos', '');
console.log(amigos) //undefined
function retornaInformacoes(url, dados = ''){
  $.ajax({
     type: 'post',
     url: url,
     data: dados,
     dataType: 'json',
     success: informacoes =>{
        console.log(informacoes) // aqui mostra os dados
         return informacoes;
     },
     error: erro =>{
         return erro
     }
 })
}
  • This will actually happen because of the asynchronous behavior of JS, what you intend to do with this return?

  • I will show the data to the user, I am trying to do this, because I created several $.ajax, I thought better to create a function that only received the url and the data and within each function treat differently

  • In the Success callback, you can place your function that handles the DOM and displays the data to the user.

  • I had already done this, but as I told you, I am repeating many $.ajax and wanted to avoid this, creating a function that returns the data and treat within the function, this can do ? using the $.ajax

1 answer

4


What happens is that you are inside a function of a callback, then the return that you are using will not return a function value retornaInformacoes, but of the callback:

function retornaInformacoes() {
  $.ajax({
    // ...
    success: (data) => {
      // O return abaixo está retornando um valor para a função
      // que você passou como callback. (A arrow function).
      return data;
    }
  });
}

And the callbacks are being used since the $.ajax is an asynchronous operation. Therefore, there is no way not to use them in this case.

So what you need to do is get your function retornaInformacoes accepted a callback or return a Promise. Below I will demonstrate the two cases...

Passing a callback

Personally, I would not use that approach, since nowadays, with the new Features Javascript (like promises), callbacks are not the best option.

But if you are running your code in environments that may not support these new Ports, I suggest you move forward with this approach. However, how are you utilizing Arrow functions and other more modern features of Javascript in your example, this does not seem to me your case.

Anyway, if you want to use a callback you can do so:

function getData(url, callbackFn) {
  $.ajax({
    url,
    success: (data) => {
      // Note que estamos invocando a função de callback assim que a
      // chamada AJAX é finalizada com êxito.
      //
      // NOTA:
      // Como não houveram erros, estamos passando como primeiro
      // argumento o valor `null`, já que, por convenção, em um callback,
      // os erros vêm no primeiro parâmetro.
      callbackFn(null, data);
    },
    error: (error) => {
      // Note que agora, como houve erro, estamos passando como
      // primeiro argumento do callback o nosso objeto de erros.
      callbackFn(error, null);
    }
  });
}

// Para usar, só precisamos passar uma função como callback.
// No nosso caso, essa função deverá ser passada como segundo argumento.
//
// O seu primeiro parâmetro será um eventual erro;
// O segundo parâmetro serão os dados.
getData('https://api.github.com/users/lffg', (error, data) => {
  if (error) {
    console.error('ERR! Houve um erro!');
  } else {
    console.log(`${data.login} tem ${data.public_repos} repositórios no GitHub!`);
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Using promises (Promise)

This, in my opinion, is the best option to consider nowadays when working with asynchronous operations in Javascript in cases like this.

Just do it like this:

function getData(url) {
  // Note que a nossa função `getData` sempre retornará uma nova `Promise`.
  //
  // Como você pode ver na linha abaixo, as promessas recebem dois
  // parâmetros, um `resolve` e outro `reject`. Você deverá usá-los para indicar
  // a resolução ou rejeição da nossa nova promessa.
  return new Promise((resolve, reject) => {
    $.ajax({
      url,
      success: (data) => {
        // Note abaixo que estamos chamando o `resolve` da nossa `Promise`:
        resolve(data);
      },
      error: (error) => {
        // Note abaixo que estamos chamando o `reject` da nossa `Promise`:
        reject(error);
      }
    });
  });
}

// Para usar, só precisamos chamar a função e depois "concatenar" uma chamada
// `.then` para fazer uso dos dados resolvido, e um `.catch` para tratar os
// eventuais erros.
getData('https://api.github.com/users/lffg')
  .then((data) => console.log(`${data.login} tem ${data.public_repos} repositórios no GitHub!`))
  .catch((error) => console.error('ERR! Houve um erro! ->', error));
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

As you may have seen above, promises make our code much more readable as we avoid callbacks. This becomes even more evident when you need to work with multiple asynchronous operations in a row. This approach to promises helps solve an old Javascript problem called callback Hell.

Moreover, there is another advantage to working with promises: the possibility of working with asynchronous functions (async/await). This is, in fact, one of the best! Learn more in this guide.

As an additional reading, I find it valid to read that answer, which deals with a similar subject.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.