Solucionado (ver solução)
Solucionado
(ver solução)
7
respostas

Problemas com método síncrono.

Olá. Estou com um problema um pouco chato na parte de Sincronismo de um método.

Preciso que um método seja síncrono, até ai tudo bem, utilizo Async/Await e dentro do método tudo funciona, porém, gostaria que nos módulos que utilizam este método, a execução fosse "pausada" até que fosse resolvido o método assíncrono, e não que só o interior do método fosse síncrono;

Exemplo: Esta execução esta síncrona, porém, não gostaria de fazer desta maneira

teste = async function(name, path){
    let request = await fetch(`${path}/${name}`);
    return await request.text();
}
arquivo = teste("arquivo", "./local");

Gostaria de fazer algo assim:

class File{
    public async getFile(name, path){
        let request = await fetch(`${path}/${name}`);
        return  await request.text();
    }
}
const file = new File();

arquivo = file.getFile("arquivo", "local") // Gsotaria que aqui parasse a execução até que o arquivo recebesse o retorno de file.getFile()...
console.log(arquivo)

Seria possível?

Estou testando no Chrome 66.

7 respostas

Oi Rafaela, tudo bem? acho que você pode fazer isso facilmente usando promises. Lembra, a função assíncrona usando a expressão async, retorna uma promise. Pensando assim podemos fazer:

file.getFile("arquivo", "local").then(arquivo => console.log(arquivo));

Referência: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function

Certo. O porém é que não gostaria de ter que tratar a promessa fora da classe. Gostaria que quem usasse a classe simplesmente pedisse um arquivo e recebesse uma String por exemplo.

let arquivo;

file.getFile("teste.txt", "./local")
    .then(dados => {
        console.log(dados);
        arquivo = dados;
    });

console.log(arquivo);

Recebo um "undefined" e depois a resposta da promise, no caso o "dados". O que eu gostaria era de aguardar a resolução da promise para então seguir com o código. Isso é possível? Talvez utilizar alguma outra forma de capturar o arquivo.

Sempre terei de tratar a minha promise fora da classe? Não poderia fazer de alguma maneira, dentro do método getFile()?

Desde já, agradeço.

Acho que se você fizer o await da função, vai dar certo. Ela já é async mesmo...

let arquivo = await file.getFile("teste.txt", "./local");
console.log(arquivo)

Await antes do método retorna um erro => Uncaught SyntaxError: Unexpected reserved word

Caso tenha mais ideias, agradeceria, pois ainda não consegui resolver.

Desde já, muito obrigada.

Poxa Rafaela, pelos meus conhecimentos e experiências atuais admito que não sei se isso que você quer fazer é possível.

Vejamos alguns problemas, você está usando async/await, que são pra escrever funções assíncronas como se fossem síncronas. E o fetch, é assíncrono.

Eu pensei que usar o await no getFile resolveria, por que assim o interpretador ia pausar a execução pra só depois que o valor retornado tivesse disponível, ele continuasse a execução.

Só que a gente não pode usar o await fora de funções async. Mesmo que essa função retorne uma Promise.

Mas e se a gente tirar o async/await da jogada, como fica? Bom, ai ainda teríamos o problema do fetch que returna uma promise e é portanto assíncrono.

Digamos que de alguma forma maluca você consiga também tirar o fetch da jogada, eae? Qual seria o resultado disso?

Bom, considerando que estamos no JavaScript, no navegador onde só temos uma thread, sua página travaria sempre que precisasse fazer um fetch desse tipo. Entende?

Desculpa mesmo não conseguir te ajudar nessa. De qualquer forma, eu vou ver se consigo pedir pra alguém mais experiente confirmar minha hipótese.

solução!

Eu estive fazendo uns testes e percebi que o seguinte código funciona como desejado no console do navegador:

    function Concatena(texto, concatenacao){ 
        return new Promise((resolve, reject) => {
                    setTimeout(() => {
                        resolve(texto + concatenacao)
                    },1000)})
                }

    var teste = "Olá sem promessa"

    console.log(teste)
    console.log("após sem promessa")

    teste =    await Concatena("Olá ", "com promessa").then(r=>r)

    console.log(teste)
    console.log("após com promessa")

Porém, quando eu rodava em um arquivo html eu recebia esse erro: Uncaught SyntaxError: await is only valid in async function

Eu acredito que o console do navegador seja asyncrono, e por isso lá funcione. Eu contornei esse erro isolando todo o código dentro de uma função asyncrona anonima auto executável. Resumindo, o código a baixo passou a funcionar:

<html>
  <head></head>
  <body>
    <script>

    (async function(){
    function Concatena(texto, concatenacao){ 
        return new Promise((resolve, reject) => {
                    setTimeout(() => {
                        resolve(texto + concatenacao)
                    },1000)})
                }

    var teste = "Olá sem promessa"

    console.log(teste)
    console.log("após sem promessa")

    teste =    await Concatena("Olá ", "com promessa").then(r=>r)

    console.log(teste)
    console.log("após com promessa")
    })()

    </script>
  </body>
</html>

Após verificar esses resultados, eu acabo concordando com o Wanderson, apesar de possível isolar todo o arquivo numa grande função assincrona, vão ser geradas interrupções de todo o processo a cada await. O .then() vem justamente isolar os trechos do código que tem que esperar pela resposta para que o resto do código possa seguir seu curso sem interrupção.

Bom, é isso. Espero ter contribuído de alguma forma para o assunto.

Olá. Muito obrigado, realmente me ajudaram sim. Não foi da forma que havia esperado, resolvendo a promisse dentro do método sem nada externo, porém a forma com que apresentaram usando somente o await e envolvendo todo o código em um uma função com async, resolve por hora.

Não sei se em algum momento será possível resolver de alguma outra maneira, mas para executar o que precisava está ótimo.

Muito Obrigado.