Executando verificação de segurança...
0

Não, Javascript não é assincrono

Eu postei um comentário nesse post respondendo a afirmação que "PHP não é asíncrono, assim não tem Promise." com um exemplo de porque a afirmação de ter Promise não torna uma linguagem assincrona e fui trucidado nos downvotes, tanto que tive que apagar pra proder comentar, então logo de cara, não, ter Promisse não torna nada assincrono, Promisse é Promisse, assincrono é assincrono, por exemplo, um mecanismo simples de Promisse em PHP:

<?php

class Promise {
    public $status;
    public $resolved;
    public $rejected;
    public $result;
    private static $deadPromises = 0;
    public static $promisesList = [];
    private $generator;

    public function __construct($generatorFunction){
        $this->status = "pending";
        $this->generator = $generatorFunction();

        self::$promisesList[] = $this;
        $this->resume();
    }

    public function resume() {
        if ($this->status != "pending") return;

        try {
            // Check if the generator is valid and proceed
            if ($this->generator && $this->generator->valid()) {
                $this->generator->next();
            } else {
                $this->status = "resolved";
                self::$deadPromises++;
            }
        } catch (Exception $e) {
            self::$deadPromises++;
            $this->status = "rejected";
        }
    }

    static public function iterate() {
        while (true) {
            foreach (Promise::$promisesList as $promise) {
                $promise->resume();
            }
            if (Promise::$deadPromises == count(Promise::$promisesList)) {
                break;
            }
        }        
    }
}

function foreachGenerator($arr, $callback) {
    foreach ($arr as $key => $value) {
        $callback($key, $value);
        yield; // Yield here to pause after each callback execution
    }
}

// Main execution
echo "Inicio do loop principal<br>";


$p = new Promise(function () {
    return foreachGenerator([1, 2, 3, 4, 5, 6], function ($i, $v) {
        echo "$v<br>";
    });
});

echo "Fim do loop principal<br>";

// Loop das promisses
Promise::iterate();

?>

Nenhuma biblioteca extra, só PHP puro e a saída foi:

Inicio do loop principal
1
2
Fim do loop principal
3
4
5
6

Acabei de implementar um mecanismo de Promise em PHP, e PHP continua sincrono, qual o truque?

Javascript e sua forma de execução

Javascript executa as instruções linha a linha em uma única pilha de execução quando você faz:

console.log("Inicio");

p = (new Promise(() => { console.log("meio?");}));

console.log("Fim");

Javascript executa o primeiro console.log e vai para a próxima linha, só que nessa linha tem a declaração de uma Promise, uma Promise nada mais é que uma operação (e chamar uma função é uma operação) que pode ser concluída agora, depois ou nem ser concluida, é uma "promessa" como o nome sugere, então o que JS faz é executar essa função e se ela pausar sua execução por algum motivo, o interpretador segue para a próxima linha, que no caso é outro console.log, mas ele não só ignora ela, ele armazena essa Promise, depois que tudo que não for executado, o interpretador põe cada uma das promises que você declarou na pilha de execução e vai verificando o estado, enquanto estiver pending ela despausa a execução e segue para a próxima até que todas ou tenham como o estado seja fulfilled ou rejected, quando o estado mudar para um desses dois ela chama a função callback que você passou em thene catch respectivamente

Tirando a prova

Você pode ainda estar revoltado comigo achando que eu estou inventando que quero te enganar mas se liga só:

console.log("Inicio");

function* gerador1() {
    let n = -1;
    while (n < 10) {
        n+=2;
        yield n;
    }
}

function* gerador2() {
    let n = 0;
    while (n < 10) {
        n+=2;
        yield n;
    }
}

const p1 = new Promise((resolve) => {
    const generator = gerador1();
    const interval = setInterval(() => {
        const next = generator.next();
        if (next.done) {
            clearInterval(interval);
        } else {
            console.log(next.value);
        }
    }, 1);
});


const p2 = new Promise((resolve) => {
    const generator = gerador2();
    const interval = setInterval(() => {
        const next = generator.next();
        if (next.done) {
            clearInterval(interval);
        } else {
            console.log(next.value);
        }
    }, 1);
});
console.log("Fim");

Ao colar isso no console do navegador, você verá a saída:

Inicio
Fim
undefined
1
2
3
4
5
6
7
8
9
10
11

O undefined indica que a pilha de execução linha a linha seguiu conforme previsto, e a sequência de 1 a 11 demostra que p1 e p2 foram alternadas também conforme previsto, uma linguagem verdadeiramente assincrona possui mais de uma pilha de execução o que não é o caso de JS, e pilhas de execução não são threads diferente, então resumindo, assincronismo em JS é apenas uma ilusão de percepção, muito bem feita mas umas ilusão, um último exemplo caso por qualquer motivo que seja você ainda dúvide que JS é sincrono e assincronismo não é um truque:

function* gerador1() {
    let n = -1;
    while (n < 10) {
        n+=2;
        yield n;
    }
}

const p1 = new Promise((resolve) => {
    const generator = gerador1();
    const interval = setInterval(() => {
        const next = generator.next();
        if (next.done) {
            clearInterval(interval);
            resolve("Sequence complete");
        } else {
            console.log(next.value);
        }
    }, 500);
});

const p2 = new Promise((resolve) => {
    const generator = gerador1();
    const interval = setInterval(() => {
        const next = generator.next();
        if (next.done) {
            clearInterval(interval);
        } else {
            alert(`P1 não executa até o fim já que a pilha é a mesma :) e eu bloqueio a pilha, para P1 executar eu preciso liberar a pilha`);
        }
    }, 500);
});

Como agora da pra notar, o que Javascript tem são açúcares sintáticos setInterval nada mais faz que executar a função passada como argumento, bloqueando a pilha de execução, e bloqueando liberando a pilha pelo tempo especificado, ou seja, não é assincronismo, mas dá pra fazer assincronismo real em javascript, mas aí, assim como PHP dependem de extensões, não é mais o foco

Carregando publicação patrocinada...
4

Acho que a discussão precisa começar com a definição do que significa ser assíncrono. Me parece que todos os comentários abaixo estão falando sobre o mesmo assunto, mas discordam sobre o que significa ser assíncrono. A especificação do ECMAScript (o nome oficial do JavaScript) menciona suas capacidades para desenvolver funções assíncronas, bem como para interagir com elas. https://tc39.es/ecma262/ Então, talvez a discussão aqui deva ser sobre o que uma linguagem precisa ter para ser considerada assíncrona.

Gostaria de pedir que o autor, ou outros que defendem que ela não é ou não suporta funções assíncronas, apresentem:

  1. A definição do que significa ser assíncrono e
    1. Um exemplo de uma outra linguagem que é considerada assíncrona e que faz algo que não pode ser reproduzido em JavaScript com suas bibliotecas padrão.

Acho que isso ajudaria no entendimento.

Obrigado

2

Cristian, claramente o autor do post está confuso no conceito do que é ser assíncrono.
A definição foi colocada explicitamente ou implicitamente em outros comentários, não tem muito o que discutir.

O que eu acho que ele realmente está querendo dizer é sobre concorrência ou paralelismo na execução das threads.

No entanto, o Javascript (que quer dizer mais sobre sintaxe aqui) nem deveria entrar em discussão, pois seguindo a especificação do ECMAScript que você mesmo compartilhou, há os "motores" responsáveis por implementar isso e aí temos uma gama completa de implementações para usos diferentes.

O que eu tentei argumentar com o autor é que ele está discutindo algo que conceitualmente estava errado desde o início, todo o resto é consequência disso.

0

Cristian, claramente o autor do post está confuso no conceito do que é ser assíncrono.
O que eu tentei argumentar com o autor é que ele está discutindo algo que conceitualmente estava errado desde o início, todo o resto é consequência disso.

Ainda estou esperando seu exemplo de código onde JS cumpre os requisitos que você mesmo propos para definir uma linguagem como assíncrona, a documentação de javascript chamar de assincrono, não torna assincrono, apenas diz que dentro do conceito da linguagem é assincrono, fora dela é outra questão, poderia por exemplo simular a concorrencia das gorrotinas em javascript

1

Sim, elixir/Erlang, go, v todas possuem greenthreads roda em uma única cpu, porém roda assíncronamente.

Tenho duas fontes, uma com um exemplo dado por Fabio Akita em vídeo: The Elixir of Life por Fabio Akita - DevInSantos 2015

E a outra é uma pergunta feita no site o Elixir: How are Elixir processes lightweight?

Não é que sou hate de javascript não, tem seus pontos negativos, mas não é um problema pra mim, além de ter me feito sentido o que foi dito no post original eu lembrei desse vídeo acima onde explicava isso.

E agradeço por sua forma serena de alcamar os animos de todos.

2

Obrigado pela resposta! O vídeo me ajudou a compreender melhor. Acho que a confusão é em distinguir entre multithreading e assincronia.

No vídeo, se eu entendi direito, ele menciona que Elixir é multithread e, como você disse, usa green threads. Já o JavaScript não é multithread, mas isso não significa que não seja assíncrono.

No exemplo do vídeo, ele é injusto com o JavaScript, pois utiliza uma função sleep bloqueante, que nao é parte da linguagem,mas uma biblioteca que ele installou, enquanto em Elixir ele usa uma função não bloqueante (de acordo com ele mesmo). Se ele usasse uma função bloqueante em Elixir e forçasse a execução em uma única thread, teria o mesmo problema.

Se esse é o caso e o JavaScript executa código assíncrono, então, desde que a função seja não bloqueante como a do exemplo em Elixir, deveria ser possível reproduzir o mesmo comportamento e realizar 400 chamadas em 4 segundos, correto? Decidi tentar! :)

Abaixo está a minha reprodução do código do vídeo usando a mesma função bloqueante.

var express = require("express");
var router = express.Router();

router.get("/", function (req, res) {
  require("sleep").sleep(1);
  res.json({ message: "Hello World!" });
});

module.exports = router;

function startServer() {
  var app = express();
  app.use(router);
  app.listen(3002);
  console.log("Server started at http://localhost:3002");
}

startServer();

E aqui está o resultado

Javascript Async siege -r 1 -c 10 http://localhost:3002
** SIEGE 4.1.6
** Preparing 10 concurrent users for battle.
The server is now under siege...
HTTP/1.1 200     1.02 secs:      26 bytes ==> GET  /
HTTP/1.1 200     2.03 secs:      26 bytes ==> GET  /
HTTP/1.1 200     3.03 secs:      26 bytes ==> GET  /
HTTP/1.1 200     4.04 secs:      26 bytes ==> GET  /
HTTP/1.1 200     5.05 secs:      26 bytes ==> GET  /
HTTP/1.1 200     6.05 secs:      26 bytes ==> GET  /
HTTP/1.1 200     7.05 secs:      26 bytes ==> GET  /
HTTP/1.1 200     8.06 secs:      26 bytes ==> GET  /
HTTP/1.1 200     9.06 secs:      26 bytes ==> GET  /
HTTP/1.1 200    10.07 secs:      26 bytes ==> GET  /

Transactions:                     10 hits
Availability:                 100.00 %
Elapsed time:                  10.07 secs
Data transferred:               0.00 MB
Response time:                  5.55 secs
Transaction rate:               0.99 trans/sec
Throughput:                     0.00 MB/sec
Concurrency:                    5.51
Successful transactions:          10
Failed transactions:               0
Longest transaction:           10.07
Shortest transaction:           1.02

Usando uma função bloqueante, consegui reproduzir a mesma lentidão mostrada no vídeo.

Agora, veja o que acontece se eu usar uma função sleep que não bloqueia:

var express = require("express");
var router = express.Router();

function sleep(ms) {
  return new Promise((resolve) => {
    setTimeout(resolve, ms);
  });
}

router.get("/", function (req, res) {
  //   require("sleep").sleep(1);
  sleep(1000).then(() => {
    res.json({ message: "Hello World!" });
  });
});

module.exports = router;

function startServer() {
  var app = express();
  app.use(router);
  app.listen(3002);
  console.log("Server started at http://localhost:3002");
}

startServer();

Resultado:

(base) ➜  Javascript Async siege -r 1 -c 10 http://localhost:3002 
** SIEGE 4.1.6
** Preparing 10 concurrent users for battle.
The server is now under siege...
HTTP/1.1 200     1.01 secs:      26 bytes ==> GET  /
HTTP/1.1 200     1.01 secs:      26 bytes ==> GET  /
HTTP/1.1 200     1.01 secs:      26 bytes ==> GET  /
HTTP/1.1 200     1.01 secs:      26 bytes ==> GET  /
HTTP/1.1 200     1.01 secs:      26 bytes ==> GET  /
HTTP/1.1 200     1.01 secs:      26 bytes ==> GET  /
HTTP/1.1 200     1.01 secs:      26 bytes ==> GET  /
HTTP/1.1 200     1.02 secs:      26 bytes ==> GET  /
HTTP/1.1 200     1.02 secs:      26 bytes ==> GET  /
HTTP/1.1 200     1.02 secs:      26 bytes ==> GET  /

Transactions:                     10 hits
Availability:                 100.00 %
Elapsed time:                   1.02 secs
Data transferred:               0.00 MB
Response time:                  1.01 secs
Transaction rate:               9.80 trans/sec
Throughput:                     0.00 MB/sec
Concurrency:                    9.93
Successful transactions:          10
Failed transactions:               0
Longest transaction:            1.02
Shortest transaction:           1.01

Observe que cada requisição levou cerca de 1 segundo, e o tempo total foi 1.02 segundos.

Posso até reproduzir o teste mais pesado do vídeo, com 2 repetições e 200 usuários paralelos:

(base) ➜  Javascript Async siege -r 2 -c 200 http://localhost:3002
** SIEGE 4.1.6
** Preparing 200 concurrent users for battle.
The server is now under siege...
HTTP/1.1 200     1.01 secs:      26 bytes ==> GET  /
HTTP/1.1 200     1.01 secs:      26 bytes ==> GET  /
....
HTTP/1.1 200     1.02 secs:      26 bytes ==> GET  /
HTTP/1.1 200     1.02 secs:      26 bytes ==> GET  /

Transactions:                    400 hits
Availability:                 100.00 %
Elapsed time:                   2.08 secs
Data transferred:               0.01 MB
Response time:                  1.03 secs
Transaction rate:             192.31 trans/sec
Throughput:                     0.00 MB/sec
Concurrency:                  197.96
Successful transactions:         400
Failed transactions:               0
Longest transaction:            1.06
Shortest transaction:           1.00

Note como as requisições individuais continuam em torno de 1 segundo, e o total é 2.08 segundos, mais rápido que Elixir no vídeo.

Com relação ao primeiro ponto, o JavaScript roda código assíncrono e consegue responder a chamadas em paralelo, mesmo usando uma única thread. No entanto, é importante lembrar que, se o código for escrito de forma síncrona, ele não será executado de maneira assíncrona. Cabe ao desenvolvedor garantir que o código seja escrito para rodar assincronamente.

Quando o JavaScript encontra funções assíncronas por natureza, como operações de I/O, ele retorna a execução para o fluxo principal do código, permitindo que outras instruções continuem sem esperar. Porém, se o código nunca chegar a uma função assíncrona, ele será executado de forma totalmente síncrona. No meu código acima, essa função assíncrona é o setTimeout. Em algumas linguagem como Python, o desenvolvedor tem que fazer isto explicitamente.

JavaScript se destacou justamente por facilitar a execução de funções de I/O, como leitura de arquivos e chamadas de rede de maneira assíncrona, permitindo que o código continue avançando sem esperar pela resposta do servidor remoto.

O que JavaScript não faz é executar código em paralelo. Todo o código roda em uma única thread e em um event loop. Portanto, se houver algo pesado para processar, como uma grande quantidade de dados, o JavaScript ficará limitado pela capacidade dessa única thread.

Me fale se o que escrevi faz sentido. Estou curioso para saber se consegui entender seu ponto e se estamos alinhados na diferença entre assíncrono e paralelo.

1

Cristian, macho eu criei alguns exemplos pra te dá sobre greenthread e goroutines e testei iria trazer o exemplo dos resultados quando eu percebi que o meu conhecimento de relacionado a threads estava fraco, pois acabava que não batia quando realizava o teste era muita teoria, e teoria equivocada.

E reconheço a minha confusão, peço desculpas e obrigado por sua paciência em explicar.

1

Um exemplo de uma outra linguagem que é considerada assíncrona e que faz algo que não pode ser reproduzido em JavaScript com suas bibliotecas padrão.

Goroutines, são assincronas de verdade já que são concorrentes, são single-threads e não podem ser reproduzidos em JavaScript com suas bibliotecas padrão apenas emuladas o que torna o desempenho incrívelmente lento

1

Eu programo em Go, e as goroutines não são executadas em uma única thread. Aqui está a documentação oficial do Go: https://go.dev/doc/effective_go. O segundo parágrafo da seção sobre goroutines:

Goroutines are multiplexed onto multiple OS threads so if one should block, such as while waiting for I/O, others continue to run. Their design hides many of the complexities of thread creation and management.

Esse trecho explica que as goroutines são distribuídas em múltiplas threads do sistema operacional.

1
1

Rapaz, não é possível!
O cara deu uma ótima explicação sobre o conceito, e muita gente que dúvido que leu tudo, apenas deu downvote.

A comunidade da ficando tóxica na moral mesmo!

Um rapaz abaixo, disso você não está confundindo com paralelismo, que tem haver bicho?
O cara falou todo tempo só não deixou explicito o nome concorrência.

Lembro que a um bom tempo atrás eu fiz um Schedule na linguagem Euphoria, que não tem um tipo de thread chamada cooperativa, onde não um agente superior que fica dizendo quando parar uma execução para dar pra outro executar como funciona na concorrência, então o que fiz foi criar um agent que lida com isso.

Quem quiser olhar: https://github.com/Ddiidev/AgentSchedule

Enfim, vocês precisam parar e ler atentamente.

Ótimo conteúdo xafiyom362

1

Com todo respeito, mas você só provou o contrário com seus exemplos.
Parece que você está confundindo conceitos, na minha humilde opinião, diferentes.
Como o próprio ChatGPT resumiu aqui

Em JavaScript, "assíncrono" refere-se a operações que são executadas de forma não bloqueante, permitindo que o código continue a ser executado enquanto se espera que uma operação termine. Isso é essencial para JavaScript, que é uma linguagem de execução única (single-threaded) e precisa gerenciar tarefas demoradas, como chamadas de rede, sem interromper a execução do restante do código.

Por um acaso você estaria confundindo com paralelismo?

-2

Como o próprio ChatGPT resumiu aqui

ChatGPT não é uma boa fonte porque ele se baseia em mistura de textos, por exemplo:

Em JavaScript, "assíncrono" refere-se a operações que são executadas de forma não bloqueante, permitindo que o código continue a ser executado enquanto se espera que uma operação termine.

Javascript realmente bloqueia a execução, é preciso descer o nível pra entender:

console.log("Inicio");
setInterval(() => {
  console.log("Meio");
}, 500);
console.log("Fim");

O que a linguagem está fazendo?

imprime: Inicio
coloca: console.log("Meio"); na fila de espera para cada 500ms
imprime: Fim

Note que "coloca:" é uma ação rápida, ela bloqueia a execução mas por um tempo muito pequeno (de 1 a 4ms a depender da implementação) Quando chega em imprime Fim ele faz uma busca na fila de espera, qual a próxima coisa a ser executada? Vai ter algo mais ou menos assim:

console.log("Meio");
setInterval(() => {
  console.log("Meio");
}, 500);

Então ele vai interpretar assim:

imprime: Meio
coloca: console.log("Meio"); na fila de espera para cada 500ms

Basicamente o que acontece é que javascript coloca um loop no final da pilha que executa uma função e registra a execução de novo repetindo o processo, toda vez que console.log é executado ele bloqueia, imprime e passa e toda vez que setInterval é chamado ele bloqueia, registra e passa

O que causa esse efeito é que além de ser single-threaded javascript geralmente é single-state também, state são ponteiros que recebem as pilhas de execução, não tem a ver com paralelismo multiplos states podem ou não estar em threads diferentes

Enfim, javascript parece assíncrono porque faz muito bem feito esse gerenciamento mas não é assíncrono, toda chamada "assíncrona", o que ele faz é uma técnica em sua VM chamada Out-of-Order Execution mais especificamente a forma callback queue

O erro é pensar que setInterval não é executado o que não é executado é o seu callback

1

Bem, eu só usei o ChatGPT pra resumir. Mas já que sua fonte é mais confiável, explique melhor então o seu conceito de assíncrono.

Pra mim é bem simples, como uma linguagem interpretada, o interpretador vai executar linha a linha.
No entanto, existe uma engine que tá controlando a execução da thread principal (no caso de ser single-thread) e essa engine que controla o Loop de Execução.

Se uma linha de código (linha 1) eu digo que quero uma Promise e a minha engine entende isso e já pula pra linha seguinte sem bloquear a execução do código seguinte (linha 2 em diante) jogando a execução do código (callback) da minha Promise para o Loop controlar a fila, eu estou satisfeito, pois isso é ser assíncrono, no conceito da linguagem em si.

Realmente não estou entendendo o seu ponto, seu conceito de assíncrono, no caso.

1

pois isso é ser assíncrono, no conceito da linguagem em si.

Só não é assincrono no sentido real da palavra, não tem um componente essencial para assincronismo: concorrência

1

E? Só prova que PHP é uma coisa, JavaScript é outra coisa. Cada linguagem tem sua aplicação, uma foi inventada para front, outra para back e ambas são gambiarrados o tempo todo para virar aplicação desktop, front, back e aplicativo. Moral da história: dá pra fazer merda com qualquer coisa, seja electron, node, php gtk, native php....

-1

Isso está muito errado. Sinceramente, não são surpresa os downvotes.

É uma desinformação produzida por consequência de analfabetismo funcional (quando você sabe ler a palavra, mas não sabe o significado).

Uma execução assíncrona não implica em processamento paralelo.

"Assíncrono" significa "que ocorreu fora de sincronia", ou em palavras mais simples "que ocorre em outro momento que não o momento da definição/deflagração".

Promises são assíncronas porque não se resolvem no momento em que são disparadas. Ou seja, o código posterior à deflagração da Promise é executado mesmo que a Promise não resolva. E a Promise é resolvida somente quando tudo que precisa estiver disponível. Ela fica aguardando a solução e só então é resolvida. É o mesmo caso dos eventos. A callback fica aguardando o evento ocorrer pra só então executar, portanto também é um procedimento assíncrono, porque não ocorre no momento da definição.

Portanto, sim, JavaScript também é assíncrono. E, mesmo que o PHP não tenha nativamente blocos de execussão assíncrona, nada impede uma implementação assíncrona (vide diversos pacotes disponíveis na internet para esta finalidade). Ainda, o PHP tem SplObserver e SplObservable, nativamente, que são mecanismos assíncronos, afinal, as funções só executam quando ocorre uma mudança/notificação.

Agora, se o assunto é processamento paralelo/concorrente, aí a história é outra.

0

É você estaria certo, SE javascript funcionasse assim, mas não é o caso, quando você faz:

async function exemplo() {
  console.log("Olá mundo!");
}

O que acontece internamente é:

function exemplo() {
    return function(...args) {
        return new Promise((resolve, reject) => {
            try {
                // Tenta resolver
                const result = console.log("Olá mundo!");
                if (result instanceof Promise) {
                    //Ainda não tá pronto, empilha essa Promisse no final da fila
                    result.then(resolve).catch(reject);
                } else {
                    // Opa, tá pronto empilhe as funções passadas em then
                    // e libere o fluxo
                    resolve(result);
                }
            } catch (error) {
                // Deu algum erro empilhe as funções passadas em catch
                // e libere o fluxo
                reject(error); 
            }
        });
    };
}

Ou seja, quando você chama exemplo();, a chamada de exemplo é síncrona mas ele coloca na fila de mensagem, (Message Queue), após cada chamada de função ou término de bloco javascript vai percorrer essa fila e de forma síncrona e por tanto bloqueante vai tentar resolver as promisses, resolveu? Ótimo, empilhe se houver na fila de micro tarefas, e percorra a fila de microtarefas colocando elas na callstack, as funcões passadas em then, deu ruim? Empilhe as funcões passadas em catch, ainda não resolveu? Empilhe a promise resultante da chamada no final da fila, e pula pra próxima, verificou toda a fila? Volta pra callstack e repete o ciclo, isso é o tal "Loop de Eventos", sem uma pilha de chamada extra não é assincrono, parece assincrono, em uma linguagem assíncrona você tem algo chamado concorrência mesmo sendo single treads, em Lua (que é a mais simples de evidenciar) que é puramente síncrona por design permitindo assincronismo por corrotinas para ela ser assíncrona basta instanciar um lua_state pra cada chamada assíncrona, aí sim teremos assincronia, inclusive a saída:

Inicio
Fim
undefined
1
2
3
4
5
6
7
8
9
10
11

É estatisticamente improvável, para o exemplo "tirando a prova", ele é um resultado síncrono com uma prova, as chances disso acontecer em uma linguagem assíncrona são de 1 em 11! ou seja 1 em 39.916.800, ou em percentual 0.0000025%< exemplo de tirando a prova

1

Parece que você insiste em não querer entender.

Assíncrono significa exclusivamente algo que ocorre fora do tempo, nada mais.

Não existe isso de que pra ser assíncrono é necessário ser concorrente (acontecer ao mesmo tempo, ou acontecer enquanto outra coisa acontece). As palavras são diferentes porque significam coisas diferentes.

O exemplo "tirando a prova" é assíncrono, mesmo que o resultado esteja ordenado, porque os resultados só são resolvido a cada 1ms. O runtime do resultado é diferente do runtime da invocação, ou seja, os timestamps não são o mesmo valor.

Se você quer algo concorrente, então é só instanciar um worker e pronto.