Estou tentando criar (ainda outra) linguagem que compila para JavaScript. Um dos recursos que eu gostaria de ter é a capacidade de executar operações assíncronas do JavaScript de forma síncrona (não exatamente síncrona - sem bloquear o segmento principal, é claro). Menos conversas, mais exemplos:
/* These two snippets should do exactly the same thing */
// the js way
var url = 'file.txt';
fetch(url)
.then(function (data) {
data = "(" + data + ")";
return sendToServer(data);
}).then(function (response) {
console.log(response);
});
// synchronous-like way
var url = 'file.txt';
var response = sendToServer("(" + fetch(url) + ")");
console.log(response);
Qual é a maneira mais elegante de compilá-lo de volta ao JS?
Os critérios, classificados por importância:
- atuação
- Compatibilidade com versões anteriores
- Legibilidade do código compilado (não é realmente importante)
Existem várias maneiras possíveis de implementá-lo, essas três me vieram à mente:
Usando promessas:
f(); a( b() );
se transformaria emf().then(function(){ return b() }).then(function(x){ a(x) });
- profissionais: relativamente simples de implementar, polifillable de volta ao ES3
- contras: criar uma nova função e uma instância de proxy para cada chamada de função
-
f(); a( b() );
se transformaria emyield f(); tmp = yield b(); yield a( tmp );
- pros: melhor javascript
- contras: criação de proxies, geradores e iteradores em todas as etapas, também não polifillable
- EDIT: na verdade, eles são polyfillable usando outro recompilador (por exemplo, Regenerator )
Usando XMLHttpRequest síncrono:
- solicitar um script de servidor que aguarde até outra chamada de outro lugar no código
- prós: de fato, nenhuma alteração no código, super fácil de implementar
- contras: requer script do servidor (=> sem portabilidade, somente navegador); além disso, XMLHttpRequest síncrono bloqueia o encadeamento para que não funcione
- EDIT: Na verdade, funcionaria dentro de um trabalhador
O principal problema é que não se pode dizer se uma função é assíncrona até o tempo de execução. Isso resulta nas duas soluções que, pelo menos , funcionam muito mais lentas que o JS puro. Então eu pergunto:
Existem melhores maneiras de implementar?
Das respostas:
Aguardar palavra-chave (@ MI3Guy)
- Caminho C # (o que é bom !)
- introduz uma nova palavra-chave (que pode ser disfarçada como uma função (cidadão de primeira classe) que, por exemplo, lança se o programador tentar passar como argumento)
- Como saber se essa função é assíncrona? Nenhuma outra palavra-chave!
- Toda função que contém
await
palavras-chave se torna assíncrona? - Quando o código chega
await
, ele retorna uma promessa? Mais trata como uma função comum?
- Toda função que contém
f(); a( b() );
se tornaria f().then(b).then(a);
Você não inclui funções.
synchronously (without blocking the thread, of course)
Você continua usando essa palavra. Eu não acho que significa o que você pensa que significa, porque de forma síncrona significa "bloquear o segmento".