Mausim,
A sua função fAsyncPesquisaDataset é a mesma que postou no tópico Async await para recuperar informação de dataset?
Caso seja, o problema provavelmente é esse.
JavaScript possui as ações que "bloqueiam" a execução até terminarem e tem as ações que não bloqueiam. A sua função chama a DatasetFactory.getDataset do jeito síncrono e isso bloqueia a execução até que a requisição termine. Esse bloqueio deve estar acontecendo antes do navegador conseguir alterar o valor, na tela, para "Processando...". Logo após terminar a requisição ele escreve o "Processando...", executa o for (que provavelmente é rápido) e já troca o valor para "Termininou!".
Eu tive problema similar ao usar a DatasetFactory.getDataset, de forma síncrona, com o Loading do Fluig Style. Por isso criei aquela função wrapper para converter tudo pra Promise e assim conseguir esperar a requisição terminar, mas sem bloquear a execução.
Acredito que isso resolva o seu problema.
Agora um pouco de assunto técnico da linguagem, pois acho que teve um desencontro de informações.
Isto é uma pergunta recorrente por toda a internet e por todo o mundo: por que determinados eventos ocorrem foram de ordem no javascript.
Há sempre a explicação: javascript é assíncrono, de modo instruções sucessivas (e não tratadas) são executadas sem que segunda espere a primeira ser concluída, levando assim às supresas, quando se espera que algo aconteça antes de outro.
O JS executa as ações na ordem que lhe foi entregue. O "problema" se dá por que confundimos que é "bloqueante" e o que não é.
Por exemplo:
function t1() {
for (let i = 0; i < 10000000000; ++i);
console.log('t1');
}
function t2() {
console.log('t2');
}
t1();
t2();
As funções serão executas na ordem e a execução ficará "bloqueada" na função t1 até terminar o for (isso mesmo se estivesse usando Promise). Assim será exibido no log primeiro o 't1' e depois o 't2'. Se fosse como comentou de "instruções sucessivas não tratadas serem executas em qualquer ordem" provavelmente 't2' seria impresso primeiro, não?
Temos outra complicação na história: JS não é multithread, ou seja ela não executa várias coisas ao mesmo tempo. Promises até podem parecer que são multithread.
Ocorre que usamos muito o JS com os eventos do Navegador (ou do NodeJS) e quando o evento termina ele executa uma função callback. Quando você coloca uma callback a um evento (design pattern observer) você não está executando nada no momento, então isso não é bloqueante.
setTimeout(() => console.log('setTimeout'), 0);
console.log('Hello');
A função setTimeout não é bloqueante. Ela pede pro navegador disparar a função callback quando determinado tempo passar. Por isso o console.log('Hello')
é executado exibindo o 'Hello' no log e então o navegador dispara a callback da setTimeout (afinal já se passaram 0 milissegundos) e é exibido no log o valor 'setTimeout'. Por isso parece que foram executadas fora de ordem.
O mesmo acontece quando você passa a "ouvir" determinado evento, por exemplo o evento click em um botão. Você só declarou que quando houver o click é para executar determinada callback, por isso essa instrução não é bloqueante.
Chamadas AJAX (obedecendo o A de Assíncrono) também não são bloqueantes, então o navegador executa a requisição e chama a callback quando a requisição terminar, não travando a execução.
Callbacks são ótimas, mas possuem alguns problemas com relação ao tratamento de erros, a saber a sua situação de execução e tantos outros.
Assim criaram as Promises (JQuery criou o $.Deferred) para resolver vários problemas.
// JQuery somente com callback
$.ajax({
dataType: "json",
url: url,
success: function (data1) {
if (data1.url && data1.time > 0) {
$.ajax({
dataType: "json",
url: data1.url,
success: function (data2) {
// Executa a ação
},
error: function (jqXHR, textStatus, error) {
console.log(error);
}
});
} else {
console.log('Falha ao buscar informações');
}
},
error: function (jqXHR, textStatus, error) {
console.log(error);
}
});
// Jeito "Promise" ($.Deferred)
$.getJSON(url)
.then(function (data) {
if (!data.url || data.time <= 0) {
return null;
}
return $.getJSON(data.url);
})
.then(function (data) {
if (!data) {
console.log('Falha ao buscar informações');
return
}
// Executar ação
})
.catch(function (jqxhr, textStatus, error) {
console.log(error);
});
// Usando Fetch API
fetch(url)
.then(response => response.json())
.then(data => {
if (!data.url || data.time <= 0) {
// Ao disparar uma exceção o primeiro .catch da sequência fará o tratamento
// JQuery não possui essa funcionalidade com exceções
throw 'Falha ao buscar informações';
}
return fetch(data.url).then(response => response.json());
})
.then(data => {
// Executa a ação
})
.catch(error => console.log(error));
Então fica bem melhor para efetuar o encadeamento das chamadas e é possível usar algumas opções para executar "em paralelo" as requisições não bloqueantes (JQuery possui o $.when enquanto JS nativa tem o Promise.all, Promise.race, Promise.any, etc).
Mas em várias situações precisamos de um valor de uma requisição para executar outra ação (assim como no exemplo anterior) e ter que criar várias callbacks para executar posteriormente o código só sujaria tudo (callback hell). Por isso criaram o async/await. Assim podemos esperar algo acontecer, pegar o valor e continuar ao invés de todo o trabalho de criar funções.
// Mesmo exemplo anterior, porém com async/await
async function getData(url) {
try {
const data1 = await fetch(url).then(response => response.json());
if (!data1.url || data1.time <= 0) {
throw 'Falha ao buscar informações';
}
const data2 = await fetch(data1.url).then(response => response.json());
// Executa ação com data2
} catch (error) {
console.log(error);
}
}
Esse código executa de forma assíncrona a requisição, não travando o navegador, mas espera o retorno da requisição para dar continuidade à execução do código.
Certamente me alonguei demais na questão, principalmente por que gosto de discussões assim, e devo ter explicado algo de forma não muito bem compreensível.
Qualquer dúvida ou argumento é bem vindo :)
Edit:
Hoje encontrei essa ótima palestra do Marcel explicando um pouco sobre programação síncrona e assíncrona e de uma forma bem legal sobre o código bloqueante e não-bloqueante: https://speakerdeck.com/marcelgsantos/programacao-assincrona-em-javascript-do-basico-ao-avancado