Aviso
Não instale este pacote como uma dependência! (Veja: Introdução)
Atualmente, as promessas são a maneira de fato de lidar com tarefas assíncronas em JavaScript e, por isso, são uma parte fundamental do conhecimento de qualquer desenvolvedor de Javascript.
No entanto, quando estamos aprendendo promessas pela primeira vez, apenas aprendemos o suficiente para sobreviver , ou seja, aprendemos um pouco de como usar as promessas (hoje em dia, provavelmente apenas com async/await ), o método Promise.all e é isso.
Embora essa abordagem faça sentido para iniciantes, porque é suficiente resolver a maioria dos problemas em suas vidas diárias, uma questão recorrente é que eles param por aí , ou seja, eles nunca passam por esse conhecimento inicial.
E é precisamente que isso "aprenda apenas o suficiente para obter" postura que mantém muitos desenvolvedores em seu nível atual, pois resolver problemas mais complexos requer um entendimento mais profundo.
Portanto, se você deseja levar suas habilidades de desenvolvedor para o próximo nível , nadar em águas rasas não o cortará , você deve se aprofundar , precisa entender completamente as promessas e como elas funcionam, você precisa ser proficiente em estilos async/await e then/catch captura de promessa e ser capaz de orquestrar as tarefas assíncronas no caminho mais eficiente possível.
Além disso, como as promessas são, em última análise, uma abstração para lidar com tarefas assíncronas, ser capaz de resolver problemas comuns relacionados à programação assíncrona é uma obrigação.
Com isso em mente, criamos esse projeto com precisão para ajudá -lo a fazer isso profundo mergulho em promessas e programação assíncrona.
Ao fornecer explicações e exercícios práticos em torno desses tópicos, este projeto pretende ser seu companheiro nessa jornada para dominá -los.
Mesmo se você já é um desenvolvedor experiente, pode aprender uma coisa ou duas, como, por exemplo, você pode tentar resolver concrete/parallelMaxConcurrency , concrete/concurrencyOverride , concrete/extractingResolvers e /foundation/promise pois apresentam alguns desafios interessantes.
Importante
Este projeto não se destina a pessoas que estão aprendendo promessas pela primeira vez, pois assume que você tem pelo menos algum conhecimento básico das promessas, o que elas representam e como usá -las com async/await e then/catch .
Aviso
ATENÇÃO: Este repositório não deve ser clonado, a menos que você esteja contribuindo se você for um usuário final, siga as instruções abaixo
Primeiro, para instalar o projeto, execute:
npm create promises-training@latestObservação
Este projeto é orientado a exercícios, portanto, o principal objetivo é resolvê-los.
Ocasionalmente, haverá explicações junto com os exercícios para ajudá -lo a entender o que precisa ser feito e também algum contexto sobre o problema que está sendo resolvido.
Os exercícios são divididos em três categorias:
Importante
Não há um pedido específico para categorias, você pode começar de qualquer uma delas e mudar para outro mesmo antes de terminar o outro completamente. No entanto, os exercícios têm níveis diferentes que serão discutidos a seguir.
Os exercícios estão localizados nas pastas src/exercises/<category> , onde <category> é uma das categorias mencionadas acima.
Para exercícios gráficos , as explicações básicas estão localizadas neste readme, na seção de gráficos e para cada exercício, há um graph.png que descreve o gráfico de dependência para esse exercício específico.
Para exercícios de concreto e fundação , as explicações estão localizadas no README.md dentro da pasta do exercício (por exemplo, src/exercises/concrete/parallelChunks/README.md ).
Para resolver um exercício, você precisa editar o arquivo src/exercises/<category>/<exercise>/exercise.ts .
Depois de resolver um exercício, você pode verificar sua solução em execução:
npm run check < category > / < exercise > Os testes estão localizados no src/tests .
Geralmente, você só trabalhará dentro da pasta dos exercícios, pois os testes são criados de uma maneira que eles lhe dizem exatamente o que deu errado sem precisar olhar para a implementação deles, mas se por qualquer motivo você ficar preso ou curioso, você pode espiar.
A pasta src/lib é destinada apenas ao uso interno, então não se preocupe com ela.
Além disso, para manter sua instalação adiante compatível com versões futuras, não modifique nenhum arquivo fora da pasta src/exercises .
Além das categorias, os exercícios também são divididos em níveis, onde os exercícios aumentam em dificuldade à medida que você avança nos níveis.
Existem três níveis:
Lembre -se de que essa classificação é um pouco subjetiva, então YMMV e você também não precisa necessariamente concluir todos os exercícios em um nível para passar para o próximo.
Observação
Como você pode ver, atualmente, não há muitos exercícios avançados, mas a idéia é que novos exercícios serão adicionados ao longo do tempo.
Cada exercício é acompanhado por testes automatizados para que você possa verificar sua solução.
Para executar os testes de um único exercício, execute:
npm run check < category > / < exercise > Por exemplo, para executar os testes para o exercício parallelChunks , execute: Run:
npm run check concrete/parallelChunksOu, para executar o exercício gráfico número 2, execute:
npm run check graph/2/test.test.tsObservação
No exemplo anterior, precisávamos anexar /test.test.ts ao arquivo do exercício, caso contrário, ele também seria executado para outros exercícios gráficos começando com 2 , por exemplo: exercícios de 2 a 29.
Usamos o Vitest como corredor de teste, para que todas as suas opções de CLI estejam disponíveis.
Além disso, é importante mencionar que os exercícios gráficos têm algumas peculiaridades, no sentido de que elas são geradas automaticamente a partir do próprio gráfico e, por isso, alguns exercícios têm um grande número de testes (alguns exercícios têm mais de 100 mil testes).
Obviamente, não executamos todos eles, pois seria proibitivamente lento, por isso executamos apenas um subconjunto deles e é possível ajustar o número de testes executados e também o subconjunto .
Você pode ler mais na seção Exercícios do Gráfico.
Atualmente, existem três categorias de exercícios:
Uma grande parte de lidar com tarefas assíncronas é orquestrá -las para que cada tarefa inicie o mais rápido possível e, para orquestrar adequadamente essas tarefas, precisamos entender as relações de dependência entre elas.
Nesta categoria, você receberá um gráfico de dependência em cada exercício e, em seguida, orquestrará as tarefas no gráfico da maneira mais eficiente possível.
Como o exercício é focado na própria orquestração, as tarefas são criadas chamando createPromise(label) , onde label é uma string que identifica a tarefa.
Veja este gráfico, por exemplo:

Existem duas tarefas neste gráfico, A e B e B depende de A , que é representado pela seta que sai de B e aponta para A .
Isso significa que B só pode começar depois que A terminar e A , pois não depende de nenhuma outra tarefa, pode começar imediatamente.
Assim, a implementação mais eficiente para este gráfico seria:
await createPromise ( "A" ) ;
await createPromise ( "B" ) ;As tarefas também podem depender de mais de uma tarefa:

Neste gráfico, C depende de A e B , para que ele só possa começar depois que A e B terminam.
No entanto, A e B não dependem de nenhuma outra tarefa, para que possam começar imediatamente.
A implementação mais eficiente para este gráfico seria:
await Promise . all ( [ createPromise ( "A" ) , createPromise ( "B" ) ] ) ;
await createPromise ( "C" ) ;As tarefas também podem ter vários conjuntos diferentes de dependências em que, se algum dos conjuntos estiver satisfeito, a tarefa poderá iniciar:

Neste gráfico, C depende de A ou B , que é representado usando cores diferentes para cada conjunto de dependência. As próprias cores não têm nenhum significado específico, elas são usadas assim, apenas para que as dependências sejam distinguidas uma da outra.
Portanto, C pode começar assim que A ou B terminarem.
await Promise . any ( [ createPromise ( "A" ) , createPromise ( "B" ) ] ) ;
await createPromise ( "C" ) ;Por último, mas não menos importante, as promessas têm dois resultados possíveis: eles podem ser cumpridos ou rejeitados.

Neste gráfico, temos a tarefa B , que depende da A e da tarefa C , que depende da rejeição de A
Importante
As bordas tracejadas são usadas para representar rejeições de promessa.
Isso significa que B só pode começar depois que A foi cumprido e C só pode começar depois que A for rejeitado.
Como apenas um desses resultados é possível, B ou C serão realizados.
Implementação correspondente:
try {
await createPromise ( "A" ) ;
try {
await createPromise ( "B" ) ;
} catch { }
} catch {
await createPromise ( "C" ) ;
} Ao fazer exercícios gráficos, você notará que três funções estão sendo exportadas: mixed , asyncAwait , thenCatch .
A idéia é que você forneça três implementações diferentes:
mixed : este é totalmente gratuito, você pode misturar o Async/Wait e depois/Catch,asyncAwait : Neste, você só deve usar async/aguardathenCatch : Neste, você só deve usar/captura.Dessa forma, você será proficiente em ambos os estilos de manuseio de promessas.
Além disso, no final do arquivo, você notará que as exportações estão sendo embrulhadas em um skipExercise , que ignora os testes para essa implementação específica para que não atreline a saída.
Ao implementar uma solução para cada um desses três, remova a chamada skipExercise para a implementação que deseja que os testes sejam executados. Por exemplo: se você já implementou a solução mixed , remova o skipExercise , mas mantenha os do asyncAwait e thenCatch até implementá -los.
Para ajudá -lo a depurar sua implementação para os exercícios de gráfico, criamos uma interface do usuário que permite simular diferentes "caminhos" de execução.
Para abrir a interface do usuário, corra:
npm run graph:uiA interface do usuário é servida como um aplicativo da web e parece isso.

Agora vamos explorar cada seção:

A barra lateral à esquerda permite selecionar o exercício que deseja depurar.

Esta seção superior permite selecionar a implementação que deseja depurar.

A barra lateral direita permite controlar o fluxo de execução do exercício, resolvendo/rejeitando promessas.
À medida que as promessas são criadas, novas entradas são adicionadas à barra lateral.

Esta seção no centro mostra os registros das promessas que foram criadas e resolvidas/rejeitadas em cada etapa.

Esta seção na parte inferior mostra um resumo das promessas que foram resolvidas/rejeitadas em cada etapa, em ordem.
Como os exercícios gráficos são baseados em gráficos (DUH), é possível gerar todos os testes possíveis para um determinado exercício automaticamente, que é o que fazemos.
Como se pode imaginar, o número de testes gerados às vezes é enorme, por isso temos um limite no número máximo de testes executados.
Além disso, para evitar vieses, não realizamos testes na ordem em que eles foram gerados; em vez disso, nós os embaralhamos .
Esse traslamento acontece logo após a geração dos testes, para que os testes sejam determinísticos , ou seja, toda vez que você executa os testes de exercícios gráficos, você estará executando o mesmo subconjunto de testes.
No entanto, é possível ajustar a tampa e o subconjunto de testes que são executados.
Para ajustar a tampa, você pode executar npm run graph:setGraphTestsCap <number> .
Por exemplo, para definir o limite para 10000, execute:
npm run graph:setGraphTestsCap 10000 Para ajustar o subconjunto de testes que são executados, você pode executar npm run graph:shuffleGraphTestData <graph-exercise-number> , que remodelará os testes para o exercício gráfico especificado, que resultará em um subconjunto diferente de testes.
Por exemplo, para reformular os testes para o exercício gráfico número 2, execute:
npm run graph:shuffleGraphTestData 2Os exercícios gráficos são ótimos para entender as relações de dependência entre as tarefas, no entanto, eles não cobrem o espectro completo de cenários possíveis, pois apenas tarefas cujas dependências são conhecidas no tempo de compilação e fixadas podem ser representadas por um gráfico.
Portanto, temos essa categoria de exercícios concretos, onde você receberá cenários concretos que precisará implementar.
Como cada exercício nesta categoria é único, sua descrição é colocada com sua pasta.
Os exercícios da fundação são projetados para ajudá-lo a reforçar sua compreensão dos fundamentos das promessas, reimplementando funções relacionadas à promessa e, eventualmente, a própria promessa.
As descrições são colocadas com exercícios.
As soluções para os exercícios podem ser encontradas neste repositório, por exemplo, https://github.com/henriqueinonhe/promises-trening/blob/master/src/exercises/concrete/concurrencyabort/exercise.ts.
No entanto, recomendamos que você verifique apenas as soluções depois de resolver o exercício, pois o objetivo é aprender resolvendo os exercícios.
Além disso, lembre -se de que atualmente as soluções apresentadas não são necessariamente as melhores , o que significa que, mesmo que suas soluções não se pareçam com as que você encontrará aqui, isso não significa que elas sejam ruins.
Para facilitar a atualização para versões mais recentes, criamos um script de migração que migra automaticamente sua instalação para a versão mais recente, preservando suas soluções.
Para executar o script de migração, execute:
npm create promises-training@latest -- --migrateEste projeto é licenciado no CC-BY-NC-ND 4.0.
O objetivo por trás deste projeto é ser um recurso de aprendizado gratuito e permanecer livre e acessível para sempre.
Aqui está uma sessão de perguntas e respostas de algumas perguntas comuns sobre a licença:
Posso usar este projeto para estudos auto ou em grupo?
Sim, por favor, faça.
Posso usar este projeto em um treinamento interno da empresa?
Sim, desde que você credite o projeto e deixe claro que o projeto está acessível livremente independentemente do treinamento.
Posso usar este projeto para minhas sessões de orientação/oficina pagas?
Sim, desde que você credite o projeto, deixe claro que o projeto está acessível livremente independentemente da orientação/oficina, deixe claro que você está cobrando pelo seu tempo e não pelo projeto em si, deixe claro que o projeto não faz parte do seu próprio material e deixa claro que não o endossaremos ou de seus serviços.
Posso usar este projeto para o meu curso on -line pago?
Sim, desde que você credite o projeto, deixa claro que o projeto está acessível livremente independentemente do curso on -line, deixe claro que você está cobrando pelo seu tempo e não pelo próprio projeto, deixa claro que o projeto não faz parte do seu próprio material e deixa claro que não endossarmos você ou seus serviços.
Posso criar um garfo deste projeto e usá -lo para meus próprios propósitos?
Não, você não pode. Você só pode usar este projeto como está, sem nenhuma modificação. Isso é necessário para impedir que as pessoas criem garfos e depois cobrem por elas.
Posso criar um curso on -line com base neste projeto?
Não, você não pode, porque não queremos que as pessoas criem "embalagens" em torno deste projeto e depois cobrem por elas.
Se você tiver alguma dúvida sobre a licença ou quiser falar sobre um caso de uso específico, fique à vontade para me alcançar em [email protected].