diff --git a/modules/60-asynchronous-programming/010-setTimeout/Makefile b/modules/60-asynchronous-programming/010-setTimeout/Makefile new file mode 100644 index 00000000..d0d0a48c --- /dev/null +++ b/modules/60-asynchronous-programming/010-setTimeout/Makefile @@ -0,0 +1,2 @@ +test: + @ test.sh diff --git a/modules/60-asynchronous-programming/010-setTimeout/description.es.yml b/modules/60-asynchronous-programming/010-setTimeout/description.es.yml new file mode 100644 index 00000000..df227e7a --- /dev/null +++ b/modules/60-asynchronous-programming/010-setTimeout/description.es.yml @@ -0,0 +1,44 @@ +--- +name: esperar +theory: | + JavaScript es de un solo subproceso, lo que significa que solo puede realizar una tarea a la vez. + + Para gestionar tareas que requieren tiempo (como la espera, la obtención de datos o los temporizadores) sin congelar el programa, JavaScript utiliza funciones asíncronas. + + Una herramienta asíncrona básica es setTimeout. Esta herramienta programa una función (llamada callback) para que se ejecute tras un retraso especificado (en milisegundos). + + setTimeout acepta dos argumentos: + 1. Una función callback: una función que se ejecuta posteriormente, que se pasa como argumento a otra función. + 2. Un tiempo de retraso en milisegundos. + + Ejemplo: + + ```js + const cb = () => { +   console.log('Hello after 1 second'); + }; + + setTimeout(cb, 1000); + // La devolución de llamada no se llama antes de este momento (pero no necesariamente exactamente en ese momento). + // A menudo ocurre más tarde debido al bucle de eventos y a las particularidades del lenguaje. + ``` + +instructions: | + Implemente la función waitFor(ms, callback) que llama a la devolución de llamada pasada después de ms milisegundos usando setTimeout. + + ```js + waitFor(1000, () => { + console.log('1 second has passed'); + }); + ``` + +tips: + - | + [setTimeout](https://developer.mozilla.org/es/docs/Web/API/setTimeout) + - | + [Callback](https://developer.mozilla.org/es/docs/Web/JavaScript/Guide/Callbacks) +definitions: + - name: Función de callback + description: Función pasada como argumento a otra función para ser llamada más adelante. + - name: Temporizador + description: Mecanismo para ejecutar una función después de cierto tiempo. diff --git a/modules/60-asynchronous-programming/010-setTimeout/en/EXERCISE.md b/modules/60-asynchronous-programming/010-setTimeout/en/EXERCISE.md new file mode 100644 index 00000000..0e0e0a67 --- /dev/null +++ b/modules/60-asynchronous-programming/010-setTimeout/en/EXERCISE.md @@ -0,0 +1,7 @@ +Implement the function waitFor(ms, callback) that calls the passed callback after ms milliseconds using setTimeout. + +```js +waitFor(1000, () => { + console.log('1 second has passed'); +}); +``` \ No newline at end of file diff --git a/modules/60-asynchronous-programming/010-setTimeout/en/README.md b/modules/60-asynchronous-programming/010-setTimeout/en/README.md new file mode 100644 index 00000000..74bc5a1e --- /dev/null +++ b/modules/60-asynchronous-programming/010-setTimeout/en/README.md @@ -0,0 +1,20 @@ +JavaScript is single-threaded, which means it can do only one thing at a time. +To handle tasks that take some time (like waiting, fetching data, or timers) without freezing the program, JavaScript uses asynchronous functions. + +One basic asynchronous tool is setTimeout. It schedules a function (called a callback) to run after a specified delay (in milliseconds). + +- setTimeout accepts two arguments: +  1. A callback function — a function to run later, passed as an argument to another function. +  2. A delay time in milliseconds. + +Example: + +```js +const cb = () => { +  console.log('Hello after 1 second'); +}; + +setTimeout(cb, 1000); +// The callback is called not before this time (but not necessarily exactly at the moment). +// Often it happens later due to the event loop and language specifics. +``` diff --git a/modules/60-asynchronous-programming/010-setTimeout/en/data.yml b/modules/60-asynchronous-programming/010-setTimeout/en/data.yml new file mode 100644 index 00000000..381b96bf --- /dev/null +++ b/modules/60-asynchronous-programming/010-setTimeout/en/data.yml @@ -0,0 +1,12 @@ +--- +name: wait for +tips: + - | + [setTimeout](https://developer.mozilla.org/en-US/docs/Web/API/setTimeout) + - | + [Callback](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Callbacks) +definitions: + - name: Callback + description: A function passed as an argument to another function for subsequent invocation + - name: Timer + description: A mechanism for executing a function after a certain amount of time has passed. diff --git a/modules/60-asynchronous-programming/010-setTimeout/es/EXERCISE.md b/modules/60-asynchronous-programming/010-setTimeout/es/EXERCISE.md new file mode 100644 index 00000000..5a5ef44f --- /dev/null +++ b/modules/60-asynchronous-programming/010-setTimeout/es/EXERCISE.md @@ -0,0 +1,7 @@ +Implemente la función waitFor(ms, callback) que llama a la devolución de llamada pasada después de ms milisegundos usando setTimeout. + +```js +waitFor(1000, () => { + console.log('1 second has passed'); +}); +``` \ No newline at end of file diff --git a/modules/60-asynchronous-programming/010-setTimeout/es/README.md b/modules/60-asynchronous-programming/010-setTimeout/es/README.md new file mode 100644 index 00000000..b7857f4e --- /dev/null +++ b/modules/60-asynchronous-programming/010-setTimeout/es/README.md @@ -0,0 +1,21 @@ +JavaScript es de un solo subproceso, lo que significa que solo puede realizar una tarea a la vez. + +Para gestionar tareas que requieren tiempo (como la espera, la obtención de datos o los temporizadores) sin congelar el programa, JavaScript utiliza funciones asíncronas. + +Una herramienta asíncrona básica es setTimeout. Esta herramienta programa una función (llamada callback) para que se ejecute tras un retraso especificado (en milisegundos). + +setTimeout acepta dos argumentos: +1. Una función callback: una función que se ejecuta posteriormente, que se pasa como argumento a otra función. +2. Un tiempo de retraso en milisegundos. + +Ejemplo: + +```js +const cb = () => { +  console.log('Hello after 1 second'); +}; + +setTimeout(cb, 1000); +// La devolución de llamada no se llama antes de este momento (pero no necesariamente exactamente en ese momento). +// A menudo ocurre más tarde debido al bucle de eventos y a las particularidades del lenguaje. +``` \ No newline at end of file diff --git a/modules/60-asynchronous-programming/010-setTimeout/es/data.yml b/modules/60-asynchronous-programming/010-setTimeout/es/data.yml new file mode 100644 index 00000000..79f31108 --- /dev/null +++ b/modules/60-asynchronous-programming/010-setTimeout/es/data.yml @@ -0,0 +1,12 @@ +--- +name: esperar +tips: + - | + [setTimeout](https://developer.mozilla.org/es/docs/Web/API/setTimeout) + - | + [Callback](https://developer.mozilla.org/es/docs/Web/JavaScript/Guide/Callbacks) +definitions: + - name: Función de callback + description: Función pasada como argumento a otra función para ser llamada más adelante. + - name: Temporizador + description: Mecanismo para ejecutar una función después de cierto tiempo. diff --git a/modules/60-asynchronous-programming/010-setTimeout/index.js b/modules/60-asynchronous-programming/010-setTimeout/index.js new file mode 100644 index 00000000..43232840 --- /dev/null +++ b/modules/60-asynchronous-programming/010-setTimeout/index.js @@ -0,0 +1,7 @@ +// BEGIN +const waitFor = (ms, cb) => { + setTimeout(cb, ms); +}; +// END + +export default waitFor; diff --git a/modules/60-asynchronous-programming/010-setTimeout/ru/EXERCISE.md b/modules/60-asynchronous-programming/010-setTimeout/ru/EXERCISE.md new file mode 100644 index 00000000..15243548 --- /dev/null +++ b/modules/60-asynchronous-programming/010-setTimeout/ru/EXERCISE.md @@ -0,0 +1,7 @@ +Реализуйте функцию waitFor(ms, callback), которая вызывает переданный cb через ms миллисекунд, используя setTimeout. + +```js +waitFor(1000, () => { + console.log('1 second has passed'); +}); +``` \ No newline at end of file diff --git a/modules/60-asynchronous-programming/010-setTimeout/ru/README.md b/modules/60-asynchronous-programming/010-setTimeout/ru/README.md new file mode 100644 index 00000000..020acb03 --- /dev/null +++ b/modules/60-asynchronous-programming/010-setTimeout/ru/README.md @@ -0,0 +1,20 @@ +JavaScript является однопоточным, что означает, что он может выполнять только одну задачу за раз. +Для обработки задач, требующих времени (например, ожидания, извлечения данных или таймеров) без замораживания программы, JavaScript использует асинхронные функции. + +Одним из основных асинхронных инструментов является setTimeout. Он планирует выполнение функции (называемой обратным вызовом) после указанной задержки (в миллисекундах). + +- setTimeout принимает два аргумента: +1. Функция обратного вызова — функция для выполнения позже, переданная в качестве аргумента другой функции. +2. Время задержки в миллисекундах. + +Пример: + +```js +const cb = () => { +  console.log('Hello after 1 second'); +}; + +setTimeout(cb, 1000); +// Коллбек выполняется не ранее этого времени (но не обязательно именно в этот момент). +// Часто это происходит позже из-за цикла событий и специфики языка. +``` \ No newline at end of file diff --git a/modules/60-asynchronous-programming/010-setTimeout/ru/data.yml b/modules/60-asynchronous-programming/010-setTimeout/ru/data.yml new file mode 100644 index 00000000..e5ba28c7 --- /dev/null +++ b/modules/60-asynchronous-programming/010-setTimeout/ru/data.yml @@ -0,0 +1,12 @@ +--- +name: ждать +tips: + - | + [setTimeout](https://developer.mozilla.org/ru/docs/Web/API/setTimeout) + - | + [коллбек](https://developer.mozilla.org/ru/docs/Web/JavaScript/Guide/Callbacks) +definitions: + - name: Коллбек + description: Функция, переданная в качестве аргумента другой функции для последующего вызова + - name: Таймер + description: Механизм выполнения функции по истечении определенного времени. diff --git a/modules/60-asynchronous-programming/010-setTimeout/test.js b/modules/60-asynchronous-programming/010-setTimeout/test.js new file mode 100644 index 00000000..d0c33d1a --- /dev/null +++ b/modules/60-asynchronous-programming/010-setTimeout/test.js @@ -0,0 +1,20 @@ +import { expect, test, vi} from 'vitest'; +import f from './index.js'; + +test('delay occurred', () => { + vi.useFakeTimers(); + + const callback = vi.fn(); + + f(100, callback); + + expect(callback).not.toHaveBeenCalled(); + + vi.advanceTimersByTime(99); + expect(callback).not.toHaveBeenCalled(); + + vi.advanceTimersByTime(1); + expect(callback).toHaveBeenCalledTimes(1); + + vi.useRealTimers(); +}); \ No newline at end of file diff --git a/modules/60-asynchronous-programming/020-newPromise/Makefile b/modules/60-asynchronous-programming/020-newPromise/Makefile new file mode 100644 index 00000000..d0d0a48c --- /dev/null +++ b/modules/60-asynchronous-programming/020-newPromise/Makefile @@ -0,0 +1,2 @@ +test: + @ test.sh diff --git a/modules/60-asynchronous-programming/020-newPromise/description.es.yml b/modules/60-asynchronous-programming/020-newPromise/description.es.yml new file mode 100644 index 00000000..40182222 --- /dev/null +++ b/modules/60-asynchronous-programming/020-newPromise/description.es.yml @@ -0,0 +1,50 @@ +--- +name: Espera la promesa +theory: | + JavaScript es de un solo subproceso. Para evitar que la ejecución del programa se congele mientras se espera (por ejemplo, una respuesta de un servidor o un temporizador), se utiliza la ejecución asíncrona. Una forma de hacerlo es mediante promesas. + + Una promesa es un objeto que representa el resultado de una operación asíncrona y que puede recibirse ahora, más tarde o nunca. Una promesa tiene tres estados: + + - pendiente: en espera; + - cumplido: completado correctamente; + - rechazado: se produjo un error. + + El estado se controla mediante: + - resolver: se ejecuta al completarse correctamente; + - rechazar: se ejecuta al fallar. + + ```js + const promise = new Promise((resolve, reject) => { + if (success) { // condicionalmente, todo se completó correctamente + resolve('Result of the entire execution'); + } else { + reject(new Error('Error during execution')); + } + }); + ``` +instructions: | + Implementar una función waitPromise(ms, reject) que devuelva una promesa. + + La promesa debe: + + - resolverse con la cadena "¡Listo!" después de ms milisegundos si no se pasa la instrucción reject o esta es falsa. + + - rechazar con el error "¡Error!" después de ms milisegundos si la instrucción reject es verdadera. + + Usar setTimeout para retrasar la ejecución. + + Ejemplo: + + ```js + waitPromise(1000).then(console.log); // después de 1 segundo, imprime "Done!" + + waitPromise(1000, true).catch(console.log); // después de 1 segundo, imprime "Failed!" + ``` +tips: + - > + [setTimeout](https://developer.mozilla.org/es/docs/Web/API/setTimeout) + - > + [Promise](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Promise) +definitions: + - name: Promesa + description: Un objeto que representa el resultado de una operación asincrónica, ya sea exitosa o errada. diff --git a/modules/60-asynchronous-programming/020-newPromise/en/EXERCISE.md b/modules/60-asynchronous-programming/020-newPromise/en/EXERCISE.md new file mode 100644 index 00000000..d874ede7 --- /dev/null +++ b/modules/60-asynchronous-programming/020-newPromise/en/EXERCISE.md @@ -0,0 +1,17 @@ +Implement a waitPromise(ms, reject) function that returns a promise. + +The promise should: + +- resolve with the string "Done!" after ms milliseconds if reject is not passed or is false. + +- reject with the error "Failed!" after ms milliseconds if reject is true. + +Use setTimeout to delay. + +Example: + +```js +waitPromise(1000).then(console.log); // after 1 second prints "Done!" + +waitPromise(1000, true).catch(console.log); // after 1 second prints "Failed!" +``` \ No newline at end of file diff --git a/modules/60-asynchronous-programming/020-newPromise/en/README.md b/modules/60-asynchronous-programming/020-newPromise/en/README.md new file mode 100644 index 00000000..c04a4347 --- /dev/null +++ b/modules/60-asynchronous-programming/020-newPromise/en/README.md @@ -0,0 +1,21 @@ +JavaScript is single-threaded. To avoid freezing program execution while waiting (for example, for a response from a server or a timer), asynchronous execution is used. One way is to use promises. + +A promise is an object representing the result of an asynchronous operation that can be received now, later, or never. A promise has 3 states: + +- pending - waiting; +- fulfilled - successfully completed; +- rejected - an error occurred. + +The state is controlled by: +- resolve is executed upon successful completion +- reject is executed upon failure + +```js +const promise = new Promise((resolve, reject) => { + if (success) { // conditionally everything was completed successfully + resolve('Result of the entire execution'); + } else { + reject(new Error('Error during execution')); + } +}); +``` \ No newline at end of file diff --git a/modules/60-asynchronous-programming/020-newPromise/en/data.yml b/modules/60-asynchronous-programming/020-newPromise/en/data.yml new file mode 100644 index 00000000..e073e560 --- /dev/null +++ b/modules/60-asynchronous-programming/020-newPromise/en/data.yml @@ -0,0 +1,10 @@ +--- +name: Wait Promise +tips: + - > + [setTimeout](https://developer.mozilla.org/en-US/docs/Web/API/setTimeout) + - > + [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) +definitions: + - name: Promise + description: An object representing the result of an asynchronous operation, either success or error. diff --git a/modules/60-asynchronous-programming/020-newPromise/es/EXERCISE.md b/modules/60-asynchronous-programming/020-newPromise/es/EXERCISE.md new file mode 100644 index 00000000..e75daadd --- /dev/null +++ b/modules/60-asynchronous-programming/020-newPromise/es/EXERCISE.md @@ -0,0 +1,17 @@ +Implementar una función waitPromise(ms, reject) que devuelva una promesa. + +La promesa debe: + +- resolverse con la cadena "¡Listo!" después de ms milisegundos si no se pasa la instrucción reject o esta es falsa. + +- rechazar con el error "¡Error!" después de ms milisegundos si la instrucción reject es verdadera. + +Usar setTimeout para retrasar la ejecución. + +Ejemplo: + +```js +waitPromise(1000).then(console.log); // después de 1 segundo, imprime "Done!" + +waitPromise(1000, true).catch(console.log); // después de 1 segundo, imprime "Failed!" +``` \ No newline at end of file diff --git a/modules/60-asynchronous-programming/020-newPromise/es/README.md b/modules/60-asynchronous-programming/020-newPromise/es/README.md new file mode 100644 index 00000000..35b3b1e3 --- /dev/null +++ b/modules/60-asynchronous-programming/020-newPromise/es/README.md @@ -0,0 +1,21 @@ +JavaScript es de un solo subproceso. Para evitar que la ejecución del programa se congele mientras se espera (por ejemplo, una respuesta de un servidor o un temporizador), se utiliza la ejecución asíncrona. Una forma de hacerlo es mediante promesas. + +Una promesa es un objeto que representa el resultado de una operación asíncrona y que puede recibirse ahora, más tarde o nunca. Una promesa tiene tres estados: + +- pendiente: en espera; +- cumplido: completado correctamente; +- rechazado: se produjo un error. + +El estado se controla mediante: +- resolver: se ejecuta al completarse correctamente; +- rechazar: se ejecuta al fallar. + +```js +const promise = new Promise((resolve, reject) => { + if (success) { // condicionalmente, todo se completó correctamente + resolve('Result of the entire execution'); + } else { + reject(new Error('Error during execution')); + } +}); +``` \ No newline at end of file diff --git a/modules/60-asynchronous-programming/020-newPromise/es/data.yml b/modules/60-asynchronous-programming/020-newPromise/es/data.yml new file mode 100644 index 00000000..0cbb18c3 --- /dev/null +++ b/modules/60-asynchronous-programming/020-newPromise/es/data.yml @@ -0,0 +1,10 @@ +--- +name: Espera la promesa +tips: + - > + [setTimeout](https://developer.mozilla.org/es/docs/Web/API/setTimeout) + - > + [Promise](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Promise) +definitions: + - name: Promesa + description: Un objeto que representa el resultado de una operación asincrónica, ya sea exitosa o errada. diff --git a/modules/60-asynchronous-programming/020-newPromise/index.js b/modules/60-asynchronous-programming/020-newPromise/index.js new file mode 100644 index 00000000..65dfdee5 --- /dev/null +++ b/modules/60-asynchronous-programming/020-newPromise/index.js @@ -0,0 +1,15 @@ +// BEGIN +const waitPromise = (ms, shouldFail = false) => { + return new Promise((resolve, reject) => { + setTimeout(() => { + if (shouldFail) { + reject('Failed!'); + } else { + resolve('Done!'); + } + }, ms); + }); +} +// END + +export default waitPromise; diff --git a/modules/60-asynchronous-programming/020-newPromise/ru/EXERCISE.md b/modules/60-asynchronous-programming/020-newPromise/ru/EXERCISE.md new file mode 100644 index 00000000..09abe7d1 --- /dev/null +++ b/modules/60-asynchronous-programming/020-newPromise/ru/EXERCISE.md @@ -0,0 +1,17 @@ +Реализуйте функцию waitPromise(ms, reject), которая возвращает промис. + +Промис должен: + +- разрешиться со строкой "Done!" через ms миллисекунд, если reject не передан или равен false. + +- отклониться с ошибкой "Failed!" через ms миллисекунд, если reject равен true. + +Для задержки используйте setTimeout. + +Пример: + +```js +waitPromise(1000).then(console.log); // через 1 секунду выведет "Done!" + +waitPromise(1000, true).catch(console.log); // через 1 секунду выведет "Failed!" +``` \ No newline at end of file diff --git a/modules/60-asynchronous-programming/020-newPromise/ru/README.md b/modules/60-asynchronous-programming/020-newPromise/ru/README.md new file mode 100644 index 00000000..0cf7b1b9 --- /dev/null +++ b/modules/60-asynchronous-programming/020-newPromise/ru/README.md @@ -0,0 +1,21 @@ +JavaScript однопоточен. Чтобы не замораживать выполнение программы при ожидании (например, ответа от сервера или таймера), используется асинхронность. Один из способов - промисы (Promise). + +Промис - это объект, представляющий результат асинхронной операции, который может быть получен сейчас, позже или никогда. У промиса есть 3 состояния: + +- pending - ожидание; +- fulfilled - выполнен успешно; +- rejected - произошла ошибка. + +Состояние контроллируется с помощью: +- resolve выполняется при успешном выполнении +- reject выполняется при провальном выполнении + +```js +const promise = new Promise((resolve, reject) => { + if (success) { // условно всё выполнилось успешно + resolve('Result of the entire execution'); + } else { + reject(new Error('Error during execution')); + } +}); +``` \ No newline at end of file diff --git a/modules/60-asynchronous-programming/020-newPromise/ru/data.yml b/modules/60-asynchronous-programming/020-newPromise/ru/data.yml new file mode 100644 index 00000000..17e23aa9 --- /dev/null +++ b/modules/60-asynchronous-programming/020-newPromise/ru/data.yml @@ -0,0 +1,10 @@ +--- +name: Ждать промис +tips: + - > + [setTimeout](https://developer.mozilla.org/ru/docs/Web/API/setTimeout) + - > + [Promise](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Promise) +definitions: + - name: Промис + description: Объект, представляющий результат асинхронной операции — либо успех, либо ошибка. diff --git a/modules/60-asynchronous-programming/020-newPromise/test.js b/modules/60-asynchronous-programming/020-newPromise/test.js new file mode 100644 index 00000000..adf59cbe --- /dev/null +++ b/modules/60-asynchronous-programming/020-newPromise/test.js @@ -0,0 +1,26 @@ +import { beforeEach, afterEach, describe, it, expect, vi } from 'vitest'; +import f from './index.js'; + +describe('waitPromise', () => { + beforeEach(() => { + vi.useFakeTimers(); + }); + + afterEach(() => { + vi.useRealTimers(); + }); + + it('resolves with correct value after delay', async () => { + const promise = f(500); + vi.advanceTimersByTime(500); + + await expect(promise).resolves.toBe('Done!'); + }); + + it('rejects with correct error after delay', async () => { + const promise = f(500, true); + vi.advanceTimersByTime(500); + + await expect(promise).rejects.toBe('Failed!'); + }); +}); \ No newline at end of file diff --git a/modules/60-asynchronous-programming/030-resolve-reject/Makefile b/modules/60-asynchronous-programming/030-resolve-reject/Makefile new file mode 100644 index 00000000..d0d0a48c --- /dev/null +++ b/modules/60-asynchronous-programming/030-resolve-reject/Makefile @@ -0,0 +1,2 @@ +test: + @ test.sh diff --git a/modules/60-asynchronous-programming/030-resolve-reject/description.es.yml b/modules/60-asynchronous-programming/030-resolve-reject/description.es.yml new file mode 100644 index 00000000..b25de397 --- /dev/null +++ b/modules/60-asynchronous-programming/030-resolve-reject/description.es.yml @@ -0,0 +1,53 @@ +--- +name: Comprobando el pedido +theory: | + Comprensión de la resolución y el rechazo + + ```js + Resolve y reject son funciones que gestionan el resultado de una promesa. + Dentro de new Promise((resolve, reject) => { ... }), se llama a una de ellas para completar la operación asíncrona. + + resolve(value) indica éxito: + + new Promise((resolve) => { + resolve('Done'); + }).then(console.log); // 'Done' + + reject(error) señala un error: + + new Promise((_, reject) => { + reject(new Error('Error')); + }).catch(err => console.log(err.message)); // 'Error' + ' + ``` + Una promesa solo se puede resolver una vez, ya sea mediante la resolución o el rechazo. +instructions: | + Implemente la función processOrder(order), que toma un objeto con parámetros de pedido y devuelve una Promesa. + + El procesamiento del pedido debe realizarse con las siguientes comprobaciones: + + 1. Si el pedido no se paga, se devuelve una Promesa rechazada con el error "Pedido no pagado". + + 2. La cantidad del producto debe ser un número entre 1 y 100, ambos inclusive. + De lo contrario, se rechaza la Promesa con el error "La cantidad debe estar entre 1 y 100". + + 3. Si las comprobaciones son correctas, la Promesa debe ejecutarse con el objeto de pedido pasado. + + Ejemplo: + + ```js + processOrder({ item: 'banana', amount: 10, paid: true }) + .then((order) => console.log('Order processed:', order)) + .catch((err) => console.error('Error:', err.message)); + ``` +tips: + - > + [Promise](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Promise) + - > + [methods then and catch](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Promise/then) + - > + [Error Handling in Promise](https://developer.mozilla.org/es/docs/Web/JavaScript/Guide/Using_promises#ошибки) +definitions: + - name: Validación asincrónica + description: | + Validar datos mediante una promesa que se ejecuta correctamente o falla con un error. diff --git a/modules/60-asynchronous-programming/030-resolve-reject/en/EXERCISE.md b/modules/60-asynchronous-programming/030-resolve-reject/en/EXERCISE.md new file mode 100644 index 00000000..77a65af7 --- /dev/null +++ b/modules/60-asynchronous-programming/030-resolve-reject/en/EXERCISE.md @@ -0,0 +1,18 @@ +Implement the processOrder(order) function that takes an object with order parameters and returns a Promise. + +The order processing should be done with the following checks: + +1. If the order is not paid, return a rejected Promise with the error "Order is not paid". + +2. The quantity of the product must be a number from 1 to 100 inclusive. +If this is not the case, reject the Promise with the error "Quantity must be between 1 and 100". + +3. If the checks are successful, the Promise should be executed with the passed order object. + +Example: + +```js +processOrder({ item: 'banana', quantity: 10, paid: true }) +.then((order) => console.log('Order processed:', order)) +.catch((err) => console.error('Error:', err.message)); +``` \ No newline at end of file diff --git a/modules/60-asynchronous-programming/030-resolve-reject/en/README.md b/modules/60-asynchronous-programming/030-resolve-reject/en/README.md new file mode 100644 index 00000000..caf3b884 --- /dev/null +++ b/modules/60-asynchronous-programming/030-resolve-reject/en/README.md @@ -0,0 +1,20 @@ +Understanding resolve and reject + +```js +resolve and reject are functions that manage the outcome of a promise. +Inside new Promise((resolve, reject) => { ... }) one of them is called to complete the asynchronous operation. + +resolve(value) indicates success: + +new Promise((resolve) => { + resolve('Done'); +}).then(console.log); // 'Done' + +reject(error) signals an error: + +new Promise((_, reject) => { + reject(new Error('Error')); +}).catch(err => console.log(err.message)); // 'Error' +' +``` +A promise can only be resolved once, either via resolve or reject. \ No newline at end of file diff --git a/modules/60-asynchronous-programming/030-resolve-reject/en/data.yml b/modules/60-asynchronous-programming/030-resolve-reject/en/data.yml new file mode 100644 index 00000000..903e71c0 --- /dev/null +++ b/modules/60-asynchronous-programming/030-resolve-reject/en/data.yml @@ -0,0 +1,13 @@ +--- +name: Order Validation +tips: + - > + [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) + - > + [methods then and catch](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then) + - > + [Error Handling in Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises#ошибки) +definitions: + - name: Asynchronous Validation + description: | + Validation of data using a Promise that either succeeds or rejects with an error. diff --git a/modules/60-asynchronous-programming/030-resolve-reject/es/EXERCISE.md b/modules/60-asynchronous-programming/030-resolve-reject/es/EXERCISE.md new file mode 100644 index 00000000..e67478b2 --- /dev/null +++ b/modules/60-asynchronous-programming/030-resolve-reject/es/EXERCISE.md @@ -0,0 +1,18 @@ +Implemente la función processOrder(order), que toma un objeto con parámetros de pedido y devuelve una Promesa. + +El procesamiento del pedido debe realizarse con las siguientes comprobaciones: + +1. Si el pedido no se paga, se devuelve una Promesa rechazada con el error "Pedido no pagado". + +2. La cantidad del producto debe ser un número entre 1 y 100, ambos inclusive. +De lo contrario, se rechaza la Promesa con el error "La cantidad debe estar entre 1 y 100". + +3. Si las comprobaciones son correctas, la Promesa debe ejecutarse con el objeto de pedido pasado. + +Ejemplo: + +```js +processOrder({ item: 'banana', amount: 10, paid: true }) +.then((order) => console.log('Order processed:', order)) +.catch((err) => console.error('Error:', err.message)); +``` \ No newline at end of file diff --git a/modules/60-asynchronous-programming/030-resolve-reject/es/README.md b/modules/60-asynchronous-programming/030-resolve-reject/es/README.md new file mode 100644 index 00000000..0977fefc --- /dev/null +++ b/modules/60-asynchronous-programming/030-resolve-reject/es/README.md @@ -0,0 +1,20 @@ +Comprensión de la resolución y el rechazo + +```js +Resolve y reject son funciones que gestionan el resultado de una promesa. +Dentro de new Promise((resolve, reject) => { ... }), se llama a una de ellas para completar la operación asíncrona. + +resolve(value) indica éxito: + +new Promise((resolve) => { + resolve('Done'); +}).then(console.log); // 'Done' + +reject(error) señala un error: + +new Promise((_, reject) => { + reject(new Error('Error')); +}).catch(err => console.log(err.message)); // 'Error' +' +``` +Una promesa solo se puede resolver una vez, ya sea mediante la resolución o el rechazo. \ No newline at end of file diff --git a/modules/60-asynchronous-programming/030-resolve-reject/es/data.yml b/modules/60-asynchronous-programming/030-resolve-reject/es/data.yml new file mode 100644 index 00000000..662b7a91 --- /dev/null +++ b/modules/60-asynchronous-programming/030-resolve-reject/es/data.yml @@ -0,0 +1,13 @@ +--- +name: Comprobando el pedido +tips: + - > + [Promise](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Promise) + - > + [methods then and catch](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Promise/then) + - > + [Error Handling in Promise](https://developer.mozilla.org/es/docs/Web/JavaScript/Guide/Using_promises#ошибки) +definitions: + - name: Validación asincrónica + description: | + Validar datos mediante una promesa que se ejecuta correctamente o falla con un error. diff --git a/modules/60-asynchronous-programming/030-resolve-reject/index.js b/modules/60-asynchronous-programming/030-resolve-reject/index.js new file mode 100644 index 00000000..6a60e68d --- /dev/null +++ b/modules/60-asynchronous-programming/030-resolve-reject/index.js @@ -0,0 +1,19 @@ +// BEGIN +const processOrder = (order) => { + return new Promise((resolve, reject) => { + if (!order.paid) { + reject(new Error('Order is not paid')); + return; + } + + if (order.quantity < 1 || order.quantity > 100) { + reject(new Error('Quantity must be between 1 and 100')); + return; + } + + resolve(order); + }); +}; +// END + +export default processOrder; diff --git a/modules/60-asynchronous-programming/030-resolve-reject/ru/EXERCISE.md b/modules/60-asynchronous-programming/030-resolve-reject/ru/EXERCISE.md new file mode 100644 index 00000000..80b30ade --- /dev/null +++ b/modules/60-asynchronous-programming/030-resolve-reject/ru/EXERCISE.md @@ -0,0 +1,16 @@ +Реализуйте функцию processOrder(order), которая принимает объект с параметрами заказа и возвращает Promise. + +Обработка заказа должна проходить с такими проверками: + +1. Если заказ не оплачен, возвращать отклонённый Promise с ошибкой "Order is not paid". +2. Количество товара должно быть числом от 1 до 100 включительно. + Если это не так, отклонять Promise с ошибкой "Quantity must be between 1 and 100". +3. Если проверки прошли успешно, Promise должен выполниться с переданным объектом заказа. + +Пример: + +```js +processOrder({ item: 'banana', quantity: 10, paid: true }) + .then((order) => console.log('Order processed:', order)) + .catch((err) => console.error('Error:', err.message)); +``` \ No newline at end of file diff --git a/modules/60-asynchronous-programming/030-resolve-reject/ru/README.md b/modules/60-asynchronous-programming/030-resolve-reject/ru/README.md new file mode 100644 index 00000000..41aeefb4 --- /dev/null +++ b/modules/60-asynchronous-programming/030-resolve-reject/ru/README.md @@ -0,0 +1,21 @@ +Понимание resolve и reject + +```js +resolve и reject - это функции, с помощью которых происходит управление результатом промиса. +Внутри new Promise((resolve, reject) => { ... }) вызывается одна из них, чтобы завершить асинхронную операцию. + +resolve(value) означает успешное выполнение: + +new Promise((resolve) => { + resolve('Done'); +}).then(console.log); // 'Done' + + +reject(error) сигнализирует об ошибке: + +new Promise((_, reject) => { + reject(new Error('Error')); +}).catch(err => console.log(err.message)); // 'Error' +' +``` +Промис можно завершить только один раз - либо через resolve, либо через reject. diff --git a/modules/60-asynchronous-programming/030-resolve-reject/ru/data.yml b/modules/60-asynchronous-programming/030-resolve-reject/ru/data.yml new file mode 100644 index 00000000..517528d1 --- /dev/null +++ b/modules/60-asynchronous-programming/030-resolve-reject/ru/data.yml @@ -0,0 +1,13 @@ +--- +name: Проверка заказа +tips: + - > + [Promise](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Promise) + - > + [methods then and catch](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Promise/then) + - > + [Error Handling in Promise](https://developer.mozilla.org/ru/docs/Web/JavaScript/Guide/Using_promises#ошибки) +definitions: + - name: Асинхронная валидация + description: | + Проверка данных с помощью Promise, которая либо завершается успешно, либо отклоняется с ошибкой. diff --git a/modules/60-asynchronous-programming/030-resolve-reject/test.js b/modules/60-asynchronous-programming/030-resolve-reject/test.js new file mode 100644 index 00000000..903a0100 --- /dev/null +++ b/modules/60-asynchronous-programming/030-resolve-reject/test.js @@ -0,0 +1,38 @@ +import {describe, it, expect} from 'vitest'; +import f from './index.js'; + +describe('proccessOrder', () => { + it('resolves for valid order', () => { + const order = { item: 'apple', quantity: 10, paid: true }; + return f(order).then((result) => { + expect(result).to.deep.equal(order); + }); + }); + + it('rejects if order is not paid', () => { + const order = { item: 'banana', quantity: 5, paid: false }; + return f(order) + .then(() => Promise.reject(new Error('Expected method to reject.'))) + .catch((err) => { + expect(err.message).to.equal('Order is not paid'); + }); + }); + + it('rejects if quantity is less than 1', () => { + const order = { item: 'banana', quantity: 0, paid: true }; + return f(order) + .then(() => Promise.reject(new Error('Expected method to reject.'))) + .catch((err) => { + expect(err.message).to.equal('Quantity must be between 1 and 100'); + }); + }); + + it('rejects if quantity is greater than 100', () => { + const order = { item: 'banana', quantity: 101, paid: true }; + return f(order) + .then(() => Promise.reject(new Error('Expected method to reject.'))) + .catch((err) => { + expect(err.message).to.equal('Quantity must be between 1 and 100'); + }); + }); +}); \ No newline at end of file diff --git a/modules/60-asynchronous-programming/040-then-catch/Makefile b/modules/60-asynchronous-programming/040-then-catch/Makefile new file mode 100644 index 00000000..d0d0a48c --- /dev/null +++ b/modules/60-asynchronous-programming/040-then-catch/Makefile @@ -0,0 +1,2 @@ +test: + @ test.sh diff --git a/modules/60-asynchronous-programming/040-then-catch/description.es.yml b/modules/60-asynchronous-programming/040-then-catch/description.es.yml new file mode 100644 index 00000000..3e93e11b --- /dev/null +++ b/modules/60-asynchronous-programming/040-then-catch/description.es.yml @@ -0,0 +1,80 @@ +--- +name: Cadena de promesas +theory: | + Una de las principales formas de gestionar tareas asíncronas son las cadenas .then(). Permiten procesar el resultado de una tarea y pasarlo a la siguiente. + + ```js + Los siguientes métodos se utilizan para trabajar con promesas: + + - .then() - se llama cuando la promesa se ejecuta correctamente. + - .catch() - se llama cuando se produce un error. + + Cada `.then()` y `catch` devuelven una nueva Promesa, lo que permite construir una cadena: + + Existe una cadena de `.then()` y `.catch()`. + + Ejemplo de cadena: + + new Promise((resolve, reject) => { + console.log('beginning of promise'); + resolve('Success on the first step'); + }) + .then((data) => { + console.log('1. first then:', data); + return 'Success on the second step'; + }) + .then((data) => { + console.log('2. second then:', data); + // Generar un error. Normalmente, se genera un error en el proceso para su posterior procesamiento. + throw new Error('Error on the second step'); + }) + .then((data) => { + // No se ejecutará debido a un error en la anterior; el código pasará a la siguiente. catch + console.log('3. third then:', data); + return 'Success on the 4th step'; + }) + .catch((__error) => { // __error o e se suele pasar a catch + // Se detectó un error de uno de los "then" anteriores; de lo contrario, catch no se habría ejecutado. + console.log('Catch caught error:', __error.message); + return 'Error processing completed'; + }) + .then((data) => { + // Continúa después del código catch subsiguiente. + console.log('4. last then:', data); + }); + + La consola mostrará: + + beginning of promise + 1. first then: Success on the first step + 2. second then: Success on the second step + Catch caught error: Error on the second step + 4. last then: Error processing completed + + - .then() y .catch() devuelven una nueva promesa para que puedas construir cadenas. - Los errores dentro de .then() se pasan automáticamente al .catch() más cercano. + - Después de .catch(), la ejecución continúa en el siguiente .then() (si lo hay). + ``` +instructions: | + Implementa una función chainProcess que toma un número inicial y devuelve una Promesa. + + Debe realizar los siguientes pasos: + + 1. Incrementar el valor en 2 y pasarlo. + 2. Multiplicar el resultado por 3 y pasarlo. + 3. Si el resultado es mayor que 50, generar un error con el texto 'Too big!'. + 4. De lo contrario, devolver el valor como correcto. + + ```js + chainProcess(5).then(console.log); // 21 + chainProcess(20).catch(console.log); // Too big! + ``` +tips: + - > + [Promise](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Promise) + - > + [then](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Promise/then) + - > + [catch](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Promise/catch) +definitions: + - name: Cadena de promesas + description: Transferencia progresiva del resultado de un "entonces" a otro, con gestión centralizada de errores. diff --git a/modules/60-asynchronous-programming/040-then-catch/en/EXERCISE.md b/modules/60-asynchronous-programming/040-then-catch/en/EXERCISE.md new file mode 100644 index 00000000..68209f83 --- /dev/null +++ b/modules/60-asynchronous-programming/040-then-catch/en/EXERCISE.md @@ -0,0 +1,13 @@ +Implement a chainProcess function that takes an initial number and returns a Promise. + +It should perform the following steps: + +1. Increment the value by 2 and pass it on. +2. Multiply the result by 3 and pass it on. +3. If the result is greater than 50, throw an error with the text 'Too big!'. +4. Otherwise, return the value as a success. + +```js +chainProcess(5).then(console.log); // 21 +chainProcess(20).catch(console.log); // Too big! +``` \ No newline at end of file diff --git a/modules/60-asynchronous-programming/040-then-catch/en/README.md b/modules/60-asynchronous-programming/040-then-catch/en/README.md new file mode 100644 index 00000000..3a1a6f81 --- /dev/null +++ b/modules/60-asynchronous-programming/040-then-catch/en/README.md @@ -0,0 +1,54 @@ +One of the main ways to manage asynchronous tasks is .then() chains. They allow you to process the result of one task and pass it to the next. + +```js +The following methods are used to work with promises: + +- .then() - called when the promise is successfully executed. +- .catch() - called when an error occurs. + +Each .then() and catch returns a new Promise, which makes it possible to build a chain: + +There is a chain of .then() and .catch() + +Example of a chain: + +new Promise((resolve, reject) => { + console.log('beginning of promise'); + resolve('Success on the first step'); +}) +.then((data) => { + console.log('1. first then:', data); + return 'Success on the second step'; +}) +.then((data) => { + console.log('2. second then:', data); + // Generate an error. Usually, an error is generated in the process for further processing + throw new Error('Error on the second step'); +}) +.then((data) => { + // will not be executed due to an error in the previous one, the code will go to the next catch + console.log('3. third then:', data); + return 'Success on the 4th step'; +}) +.catch((__error) => { // __error or e is usually passed to catch + // caught an error from one of the previous thens, otherwise catch would not have been executed + console.log('Catch caught error:', __error.message); + return 'Error processing completed'; +}) +.then((data) => { + // continue after the subsequent catch code + console.log('4. last then:', data); +}); + +The console will output: + +beginning of promise +1. first then: Success on the first step +2. second then: Success on the second step +Catch caught error: Error on the second step +4. last then: Error processing completed + +- .then() and .catch() return a new promise, so you can build chains. +- Errors within .then() are automatically passed to the nearest .catch(). +- After .catch(), execution continues in the next .then() (if any). +``` \ No newline at end of file diff --git a/modules/60-asynchronous-programming/040-then-catch/en/data.yml b/modules/60-asynchronous-programming/040-then-catch/en/data.yml new file mode 100644 index 00000000..e4889173 --- /dev/null +++ b/modules/60-asynchronous-programming/040-then-catch/en/data.yml @@ -0,0 +1,12 @@ +--- +name: Promise chain +tips: + - > + [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) + - > + [then](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then) + - > + [catch](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/catch) +definitions: + - name: Promise chain + description: Progressive transfer of result from one then to another, with centralized error handling. diff --git a/modules/60-asynchronous-programming/040-then-catch/es/EXERCISE.md b/modules/60-asynchronous-programming/040-then-catch/es/EXERCISE.md new file mode 100644 index 00000000..a6a75536 --- /dev/null +++ b/modules/60-asynchronous-programming/040-then-catch/es/EXERCISE.md @@ -0,0 +1,13 @@ +Implementa una función chainProcess que toma un número inicial y devuelve una Promesa. + +Debe realizar los siguientes pasos: + +1. Incrementar el valor en 2 y pasarlo. +2. Multiplicar el resultado por 3 y pasarlo. +3. Si el resultado es mayor que 50, generar un error con el texto 'Too big!'. +4. De lo contrario, devolver el valor como correcto. + +```js +chainProcess(5).then(console.log); // 21 +chainProcess(20).catch(console.log); // Too big! +``` \ No newline at end of file diff --git a/modules/60-asynchronous-programming/040-then-catch/es/README.md b/modules/60-asynchronous-programming/040-then-catch/es/README.md new file mode 100644 index 00000000..b1222394 --- /dev/null +++ b/modules/60-asynchronous-programming/040-then-catch/es/README.md @@ -0,0 +1,53 @@ +Una de las principales formas de gestionar tareas asíncronas son las cadenas .then(). Permiten procesar el resultado de una tarea y pasarlo a la siguiente. + +```js +Los siguientes métodos se utilizan para trabajar con promesas: + +- .then() - se llama cuando la promesa se ejecuta correctamente. +- .catch() - se llama cuando se produce un error. + +Cada `.then()` y `catch` devuelven una nueva Promesa, lo que permite construir una cadena: + +Existe una cadena de `.then()` y `.catch()`. + +Ejemplo de cadena: + +new Promise((resolve, reject) => { + console.log('beginning of promise'); + resolve('Success on the first step'); +}) +.then((data) => { + console.log('1. first then:', data); + return 'Success on the second step'; +}) +.then((data) => { + console.log('2. second then:', data); + // Generar un error. Normalmente, se genera un error en el proceso para su posterior procesamiento. + throw new Error('Error on the second step'); +}) +.then((data) => { + // No se ejecutará debido a un error en la anterior; el código pasará a la siguiente. catch + console.log('3. third then:', data); + return 'Success on the 4th step'; +}) +.catch((__error) => { // __error o e se suele pasar a catch + // Se detectó un error de uno de los "then" anteriores; de lo contrario, catch no se habría ejecutado. + console.log('Catch caught error:', __error.message); + return 'Error processing completed'; +}) +.then((data) => { + // Continúa después del código catch subsiguiente. + console.log('4. last then:', data); +}); + +La consola mostrará: + +beginning of promise +1. first then: Success on the first step +2. second then: Success on the second step +Catch caught error: Error on the second step +4. last then: Error processing completed + +- .then() y .catch() devuelven una nueva promesa para que puedas construir cadenas. - Los errores dentro de .then() se pasan automáticamente al .catch() más cercano. +- Después de .catch(), la ejecución continúa en el siguiente .then() (si lo hay). +``` \ No newline at end of file diff --git a/modules/60-asynchronous-programming/040-then-catch/es/data.yml b/modules/60-asynchronous-programming/040-then-catch/es/data.yml new file mode 100644 index 00000000..91102e61 --- /dev/null +++ b/modules/60-asynchronous-programming/040-then-catch/es/data.yml @@ -0,0 +1,12 @@ +--- +name: Cadena de promesas +tips: + - > + [Promise](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Promise) + - > + [then](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Promise/then) + - > + [catch](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Promise/catch) +definitions: + - name: Cadena de promesas + description: Transferencia progresiva del resultado de un "entonces" a otro, con gestión centralizada de errores. diff --git a/modules/60-asynchronous-programming/040-then-catch/index.js b/modules/60-asynchronous-programming/040-then-catch/index.js new file mode 100644 index 00000000..0fa75879 --- /dev/null +++ b/modules/60-asynchronous-programming/040-then-catch/index.js @@ -0,0 +1,16 @@ +// BEGIN +const chainProcess = (num) => + new Promise((resolve) => { + resolve(num); + }) + .then((value) => value + 2) + .then((value) => value * 3) + .then((value) => { + if (value > 50) { + throw new Error('Too big!'); + } + return value; + }); +// END + +export default chainProcess; diff --git a/modules/60-asynchronous-programming/040-then-catch/ru/EXERCISE.md b/modules/60-asynchronous-programming/040-then-catch/ru/EXERCISE.md new file mode 100644 index 00000000..be17dfc3 --- /dev/null +++ b/modules/60-asynchronous-programming/040-then-catch/ru/EXERCISE.md @@ -0,0 +1,13 @@ +Реализуйте функцию chainProcess, которая принимает начальное число и возвращает Promise. + +Она должна выполнять следующие шаги: + +1. Увеличить значение на 2 и передать дальше. +2. Умножить результат на 3 и передать дальше. +3. Если результат больше 50 - выбросить ошибку с текстом 'Too big!'. +4. Иначе - вернуть значение как успешное завершение. + +```js +chainProcess(5).then(console.log); // 21 +chainProcess(20).catch(console.log); // Too big! +``` \ No newline at end of file diff --git a/modules/60-asynchronous-programming/040-then-catch/ru/README.md b/modules/60-asynchronous-programming/040-then-catch/ru/README.md new file mode 100644 index 00000000..1946ea42 --- /dev/null +++ b/modules/60-asynchronous-programming/040-then-catch/ru/README.md @@ -0,0 +1,54 @@ +Один из основных способов управления асинхронными задачами - цепочки .then(). Они позволяют обрабатывать результат одной задачи и передавать его в следующую. + +```js +Для работы с промисами используются методы: + +- .then() - вызывается при успешном выполнении промиса. +- .catch() - вызывается при ошибке. + +Каждый .then() и catch возвращает новый Promise, что даёт возможность выстраивать цепочку: + +Существует цепочка из .then() и .catch() + +Пример цепочки: + +new Promise((resolve, reject) => { + console.log('beginning of promise'); + resolve('Success on the first step'); +}) +.then((data) => { + console.log('1. first then:', data); + return 'Success on the second step'; +}) +.then((data) => { + console.log('2. second then:', data); + // Генерируем ошибку. Обычно в процессе генерируется ошибка для дальнейшей обработки + throw new Error('Error on the second step'); +}) +.then((data) => { + // не выполнится из-за ошибки в предыдущем,код перейдёт в ближайший дальше catch + console.log('3. third then:', data); + return 'Success on the 4th step'; +}) +.catch((__error) => { // __error или e обычно передаётся в catch + // словил ошибку из одного из прошлых then, иначе бы catch не выполнился + console.log('Catch catched error:', __error.message); + return 'Error processing completed'; +}) +.then((data) => { + // продолжение дальше после уже catch последующего кода + console.log('4. last then:', data); +}); + +Консоль выведет: + +beginning of promise +1. first then: Success on the first step +2. second then: Success on the second step +Catch catched error: Error on the second step +4. last then: Error processing completed + +- .then() и .catch() возвращают новый промис, поэтому можно строить цепочки. +- Ошибки внутри .then() автоматически передаются в ближайший .catch(). +- После .catch() выполнение продолжается в следующем .then() (если существует). +``` \ No newline at end of file diff --git a/modules/60-asynchronous-programming/040-then-catch/ru/data.yml b/modules/60-asynchronous-programming/040-then-catch/ru/data.yml new file mode 100644 index 00000000..3991b4ba --- /dev/null +++ b/modules/60-asynchronous-programming/040-then-catch/ru/data.yml @@ -0,0 +1,12 @@ +--- +name: Цепочка Promise +tips: + - > + [Promise](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Promise) + - > + [then](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Promise/then) + - > + [catch](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Promise/catch) +definitions: + - name: Цепочка промисов + description: Поэтапная передача результата от одного then к другому, с централизованной обработкой ошибок. diff --git a/modules/60-asynchronous-programming/040-then-catch/test.js b/modules/60-asynchronous-programming/040-then-catch/test.js new file mode 100644 index 00000000..f47040ff --- /dev/null +++ b/modules/60-asynchronous-programming/040-then-catch/test.js @@ -0,0 +1,17 @@ +import { describe, it, expect } from 'vitest'; +import f from './index.js'; + +describe('chainProcess', () => { + it('should return the correct result given a valid input value', () => { + return f(5).then((result) => { + expect(result).toBe(21); // (5 + 2) * 3 + }); + }); + + it('should throw an error if the result is too big', () => { + expect.assertions(1); + return f(20).catch((e) => { + expect(e.message).toBe('Too big!'); + }); + }); +}); \ No newline at end of file diff --git a/modules/60-asynchronous-programming/050-nested-then/Makefile b/modules/60-asynchronous-programming/050-nested-then/Makefile new file mode 100644 index 00000000..d0d0a48c --- /dev/null +++ b/modules/60-asynchronous-programming/050-nested-then/Makefile @@ -0,0 +1,2 @@ +test: + @ test.sh diff --git a/modules/60-asynchronous-programming/050-nested-then/api.js b/modules/60-asynchronous-programming/050-nested-then/api.js new file mode 100644 index 00000000..95b59ce4 --- /dev/null +++ b/modules/60-asynchronous-programming/050-nested-then/api.js @@ -0,0 +1,39 @@ +const usersDB = { + 1: { id: 1, name: 'Jon', hasAccess: true }, + 2: { id: 2, name: 'Arya', hasAccess: false }, +}; + +const ordersDB = { + 1: ['sword', 'cloak'], + 2: ['dagger'], +}; + +const fetchUser = (id) => { + return new Promise((resolve) => { + setTimeout(() => { + resolve(usersDB[id] || null); + }, 100); + }); +}; + +const fetchOrders = (user) => { + return new Promise((resolve) => { + setTimeout(() => { + resolve(ordersDB[user.id] || []); + }, 100); + }); +}; + +const checkAccess = (user) => { + return new Promise((resolve) => { + setTimeout(() => { + resolve(user.hasAccess); + }, 100); + }); +}; + +export { + fetchUser, + fetchOrders, + checkAccess, +} diff --git a/modules/60-asynchronous-programming/050-nested-then/description.es.yml b/modules/60-asynchronous-programming/050-nested-then/description.es.yml new file mode 100644 index 00000000..40e1e3e5 --- /dev/null +++ b/modules/60-asynchronous-programming/050-nested-then/description.es.yml @@ -0,0 +1,44 @@ +--- +name: Recepción de pedidos de usuarios con verificación de acceso +theory: | + .then() anidado: cuando dentro de la función de retorno de un .then() se llama a otro .then(), se invoca otro .then(). Ejemplo: + + ```js + doFirst() + .then(result1 => { + return doSecond(result1) + .then(result2 => { + return doThird(result2); + }); + }); + ``` +instructions: | + En este ejercicio, necesitas implementar la función getUserOrders(id) que: + + - Obtiene el usuario asincrónicamente por su ID usando fetchUser(id) + - Comprueba si el usuario existe; de ​​lo contrario, genera el error "User not found" + - Comprueba el acceso del usuario asincrónicamente usando checkAccess(user) + - Si no hay acceso, genera el error "Access denied" + - Si hay acceso, obtiene asincrónicamente la lista de pedidos del usuario usando fetchOrders(user) + - Devuelve una promesa con un array de pedidos + + Usa .then() anidado + + Ejemplo: + + ```js + getUserOrders(1).then((orders) => { + console.log(orders); // ['sword', 'cloak'] + }).catch(console.error); + ``` +tips: + - > + [promises](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Promise) + - > + [then](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Promise/then) + - > + [catch](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Promise/catch) +definitions: + - name: Then() anidado + description: | + Llamar a `.then()` dentro de otro `.then()` para procesar operaciones asíncronas secuencialmente, donde el resultado del primer paso afecta al siguiente. diff --git a/modules/60-asynchronous-programming/050-nested-then/en/EXERCISE.md b/modules/60-asynchronous-programming/050-nested-then/en/EXERCISE.md new file mode 100644 index 00000000..a029801e --- /dev/null +++ b/modules/60-asynchronous-programming/050-nested-then/en/EXERCISE.md @@ -0,0 +1,18 @@ +In this exercise, you need to implement a function getUserOrders(id) that: + +- Asynchronously gets the user by id using fetchUser(id) +- Checks if the user exists, otherwise throws the error "User not found" +- Asynchronously checks the user's access using checkAccess(user) +- If there is no access, throws the error "Access denied" +- If there is access, asynchronously gets the list of user's orders using fetchOrders(user) +- Returns a promise with an array of orders + +Use nested .then() + +Example: + +```js +getUserOrders(1).then((orders) => { + console.log(orders); // ['sword', 'cloak'] +}).catch(console.error); +``` \ No newline at end of file diff --git a/modules/60-asynchronous-programming/050-nested-then/en/README.md b/modules/60-asynchronous-programming/050-nested-then/en/README.md new file mode 100644 index 00000000..5a0db949 --- /dev/null +++ b/modules/60-asynchronous-programming/050-nested-then/en/README.md @@ -0,0 +1,11 @@ +Nested .then() - when inside the callback of one .then() another .then() is called. Example: + +```js +doFirst() +.then(result1 => { + return doSecond(result1) + .then(result2 => { + return doThird(result2); + }); +}); +``` \ No newline at end of file diff --git a/modules/60-asynchronous-programming/050-nested-then/en/data.yml b/modules/60-asynchronous-programming/050-nested-then/en/data.yml new file mode 100644 index 00000000..1c9f0284 --- /dev/null +++ b/modules/60-asynchronous-programming/050-nested-then/en/data.yml @@ -0,0 +1,13 @@ +--- +name: Get user orders with access check +tips: + - > + [promises](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) + - > + [then](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then) + - > + [catch](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/catch) +definitions: + - name: Nested then() + description: | + Call .then() inside another .then() to process asynchronous operations sequentially, where the result of the first step affects the next. diff --git a/modules/60-asynchronous-programming/050-nested-then/es/EXERCISE.md b/modules/60-asynchronous-programming/050-nested-then/es/EXERCISE.md new file mode 100644 index 00000000..9d53f3ce --- /dev/null +++ b/modules/60-asynchronous-programming/050-nested-then/es/EXERCISE.md @@ -0,0 +1,18 @@ +En este ejercicio, necesitas implementar la función getUserOrders(id) que: + +- Obtiene el usuario asincrónicamente por su ID usando fetchUser(id) +- Comprueba si el usuario existe; de ​​lo contrario, genera el error "User not found" +- Comprueba el acceso del usuario asincrónicamente usando checkAccess(user) +- Si no hay acceso, genera el error "Access denied" +- Si hay acceso, obtiene asincrónicamente la lista de pedidos del usuario usando fetchOrders(user) +- Devuelve una promesa con un array de pedidos + +Usa .then() anidado + +Ejemplo: + +```js +getUserOrders(1).then((orders) => { + console.log(orders); // ['sword', 'cloak'] +}).catch(console.error); +``` \ No newline at end of file diff --git a/modules/60-asynchronous-programming/050-nested-then/es/README.md b/modules/60-asynchronous-programming/050-nested-then/es/README.md new file mode 100644 index 00000000..d4806c29 --- /dev/null +++ b/modules/60-asynchronous-programming/050-nested-then/es/README.md @@ -0,0 +1,11 @@ +.then() anidado: cuando dentro de la función de retorno de un .then() se llama a otro .then(), se invoca otro .then(). Ejemplo: + +```js +doFirst() +.then(result1 => { + return doSecond(result1) + .then(result2 => { + return doThird(result2); + }); +}); +``` \ No newline at end of file diff --git a/modules/60-asynchronous-programming/050-nested-then/es/data.yml b/modules/60-asynchronous-programming/050-nested-then/es/data.yml new file mode 100644 index 00000000..96381078 --- /dev/null +++ b/modules/60-asynchronous-programming/050-nested-then/es/data.yml @@ -0,0 +1,13 @@ +--- +name: Recepción de pedidos de usuarios con verificación de acceso +tips: + - > + [promises](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Promise) + - > + [then](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Promise/then) + - > + [catch](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Promise/catch) +definitions: + - name: Then() anidado + description: | + Llamar a `.then()` dentro de otro `.then()` para procesar operaciones asíncronas secuencialmente, donde el resultado del primer paso afecta al siguiente. diff --git a/modules/60-asynchronous-programming/050-nested-then/index.js b/modules/60-asynchronous-programming/050-nested-then/index.js new file mode 100644 index 00000000..ca526868 --- /dev/null +++ b/modules/60-asynchronous-programming/050-nested-then/index.js @@ -0,0 +1,22 @@ +import { fetchUser, fetchOrders, checkAccess } from './api.js' + +// BEGIN +export const getUserOrders = (id) => { + return fetchUser(id) + .then((user) => { + if (!user) { + throw new Error('User not found'); + } + + return checkAccess(user).then((access) => { + if (!access) { + throw new Error('Access denied'); + } + + return fetchOrders(user); + }); + }); +}; +// END + +export default getUserOrders; diff --git a/modules/60-asynchronous-programming/050-nested-then/ru/EXERCISE.md b/modules/60-asynchronous-programming/050-nested-then/ru/EXERCISE.md new file mode 100644 index 00000000..c96cb093 --- /dev/null +++ b/modules/60-asynchronous-programming/050-nested-then/ru/EXERCISE.md @@ -0,0 +1,17 @@ +В этом упражнении нужно реализовать функцию getUserOrders(id), которая: + +- Асинхронно получает пользователя по id с помощью fetchUser(id) +- Проверяет, существует ли пользователь, иначе выбрасывает ошибку "User not found" +- Асинхронно проверяет доступ пользователя с помощью checkAccess(user) +- Если доступа нет - выбрасывает ошибку "Access denied" +- Если доступ есть - асинхронно получает список заказов пользователя через fetchOrders(user) +- Возвращает промис с массивом заказов +Используй вложенные .then() + +Пример: + +```js +getUserOrders(1).then((orders) => { + console.log(orders); // ['sword', 'cloak'] +}).catch(console.error); +``` \ No newline at end of file diff --git a/modules/60-asynchronous-programming/050-nested-then/ru/README.md b/modules/60-asynchronous-programming/050-nested-then/ru/README.md new file mode 100644 index 00000000..34f689b1 --- /dev/null +++ b/modules/60-asynchronous-programming/050-nested-then/ru/README.md @@ -0,0 +1,11 @@ +Вложенные .then() - когда внутри коллбэка одного .then() вызывается другой .then(). Пример: + +```js +doFirst() +.then(result1 => { + return doSecond(result1) + .then(result2 => { + return doThird(result2); + }); +}); +``` \ No newline at end of file diff --git a/modules/60-asynchronous-programming/050-nested-then/ru/data.yml b/modules/60-asynchronous-programming/050-nested-then/ru/data.yml new file mode 100644 index 00000000..ce66983e --- /dev/null +++ b/modules/60-asynchronous-programming/050-nested-then/ru/data.yml @@ -0,0 +1,13 @@ +--- +name: Получение заказов пользователя с проверкой доступа +tips: + - > + [promises](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Promise) + - > + [then](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Promise/then) + - > + [catch](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Promise/catch) +definitions: + - name: Вложенные then() + description: | + Вызов .then() внутри другого .then() для последовательной обработки асинхронных операций, где результат первого шага влияет на следующий. diff --git a/modules/60-asynchronous-programming/050-nested-then/test.js b/modules/60-asynchronous-programming/050-nested-then/test.js new file mode 100644 index 00000000..84618615 --- /dev/null +++ b/modules/60-asynchronous-programming/050-nested-then/test.js @@ -0,0 +1,24 @@ +import { describe, it, expect } from 'vitest'; +import f from './index.js'; + +describe('getUserOrders', () => { + it('should return a list of orders if the user is found and has access', () => { + return f(1).then((orders) => { + expect(orders).toEqual(['sword', 'cloak']); + }); + }); + + it('should throw error if the user is not found', () => { + return f(999).catch((error) => { + expect(error).toBeInstanceOf(Error); + expect(error.message).toBe('User not found'); + }); + }); + + it('should throw error if access is not available', () => { + return f(2).catch((error) => { + expect(error).toBeInstanceOf(Error); + expect(error.message).toBe('Access denied'); + }); + }); +}); \ No newline at end of file diff --git a/modules/60-asynchronous-programming/060-promiseAll/Makefile b/modules/60-asynchronous-programming/060-promiseAll/Makefile new file mode 100644 index 00000000..d0d0a48c --- /dev/null +++ b/modules/60-asynchronous-programming/060-promiseAll/Makefile @@ -0,0 +1,2 @@ +test: + @ test.sh diff --git a/modules/60-asynchronous-programming/060-promiseAll/api.js b/modules/60-asynchronous-programming/060-promiseAll/api.js new file mode 100644 index 00000000..7d0328b7 --- /dev/null +++ b/modules/60-asynchronous-programming/060-promiseAll/api.js @@ -0,0 +1,11 @@ +const downloadFile = (fileName) => { + return new Promise((resolve) => { + setTimeout(() => { + resolve(`${fileName} loaded`); + }, Math.random() * 100); + }); +}; + +export { + downloadFile, +} \ No newline at end of file diff --git a/modules/60-asynchronous-programming/060-promiseAll/description.es.yml b/modules/60-asynchronous-programming/060-promiseAll/description.es.yml new file mode 100644 index 00000000..4f0164ed --- /dev/null +++ b/modules/60-asynchronous-programming/060-promiseAll/description.es.yml @@ -0,0 +1,43 @@ +--- +name: Carga paralela +theory: | + El método Promise.all permite ejecutar múltiples operaciones asíncronas en paralelo y obtener los resultados en cuanto se completen todas las tareas. + + Toma un array de promesas y devuelve una nueva promesa que: + + - Se resuelve en un array de resultados, en el mismo orden en que se pasaron las promesas; + - Se rechaza si al menos una de las promesas devuelve un error. + + Ejemplo: + + ```js + const task = [fetch(url1), fetch(url2)]; + Promise.all(tasks).then((responses) => { + console.log(responses); // ambos resultados en el orden en que fueron llamados + }); + ``` +instructions: | + Implementa la función `downloadAll(files)` que toma un array de nombres de archivo y devuelve una promesa que se resuelve después de que se hayan descargado todos los archivos. + + Para descargar un solo archivo, usa la función `downloadFile(fileName)`, que devuelve una promesa. + + La función `downloadAll` debe usar `Promise.all` para descargar todos los archivos en paralelo. + + Ejemplo: + + ```js + downloadAll(['1.txt', '2.txt']).then((result) => { + console.log(result); // ['1.txt loaded', '2.txt loaded'] + }); + ``` +tips: + - > + [Promise.all](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Promise/all) + - > + [Promise](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Promise) + - > + [map](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Array/map) +definitions: + - name: Promise.all + description: | + Un método que permite ejecutar múltiples operaciones asíncronas en paralelo y esperar a que se completen. Los resultados se devuelven en el mismo orden en que se pasaron las promesas originales. diff --git a/modules/60-asynchronous-programming/060-promiseAll/en/EXERCISE.md b/modules/60-asynchronous-programming/060-promiseAll/en/EXERCISE.md new file mode 100644 index 00000000..5d89a064 --- /dev/null +++ b/modules/60-asynchronous-programming/060-promiseAll/en/EXERCISE.md @@ -0,0 +1,13 @@ +Implement a function downloadAll(files) that takes an array of file names and returns a promise that resolves after all files have been downloaded. + +To download a single file, use the ready-made function downloadFile(fileName) - it returns a promise. + +The downloadAll function should use Promise.all to download all files in parallel. + +Example: + +```js +downloadAll(['1.txt', '2.txt']).then((result) => { + console.log(result); // ['1.txt loaded', '2.txt loaded'] +}); +``` \ No newline at end of file diff --git a/modules/60-asynchronous-programming/060-promiseAll/en/README.md b/modules/60-asynchronous-programming/060-promiseAll/en/README.md new file mode 100644 index 00000000..4ff0c564 --- /dev/null +++ b/modules/60-asynchronous-programming/060-promiseAll/en/README.md @@ -0,0 +1,15 @@ +The Promise.all method allows you to run multiple asynchronous operations in parallel and get the results as soon as all tasks complete. + +It takes an array of promises and returns a new promise that: + +- Resolves to an array of results, in the same order in which the promises were passed; +- Rejects if at least one of the promises returns an error. + +Example: + +```js +const tasks = [fetch(url1), fetch(url2)]; +Promise.all(tasks).then((responses) => { + console.log(responses); // both results in the order they were called +}); +``` \ No newline at end of file diff --git a/modules/60-asynchronous-programming/060-promiseAll/en/data.yml b/modules/60-asynchronous-programming/060-promiseAll/en/data.yml new file mode 100644 index 00000000..a879af87 --- /dev/null +++ b/modules/60-asynchronous-programming/060-promiseAll/en/data.yml @@ -0,0 +1,13 @@ +--- +name: Parallel Loading +tips: + - > + [Promise.all](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all) + - > + [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) + - > + [map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map) +definitions: + - name: Promise.all + description: | + A method that allows you to run multiple asynchronous operations in parallel and wait for them all to complete. The results are returned in the same order in which the original promises were passed. diff --git a/modules/60-asynchronous-programming/060-promiseAll/es/EXERCISE.md b/modules/60-asynchronous-programming/060-promiseAll/es/EXERCISE.md new file mode 100644 index 00000000..2f7baac3 --- /dev/null +++ b/modules/60-asynchronous-programming/060-promiseAll/es/EXERCISE.md @@ -0,0 +1,13 @@ +Implementa la función `downloadAll(files)` que toma un array de nombres de archivo y devuelve una promesa que se resuelve después de que se hayan descargado todos los archivos. + +Para descargar un solo archivo, usa la función `downloadFile(fileName)`, que devuelve una promesa. + +La función `downloadAll` debe usar `Promise.all` para descargar todos los archivos en paralelo. + +Ejemplo: + +```js +downloadAll(['1.txt', '2.txt']).then((result) => { + console.log(result); // ['1.txt loaded', '2.txt loaded'] +}); +``` \ No newline at end of file diff --git a/modules/60-asynchronous-programming/060-promiseAll/es/README.md b/modules/60-asynchronous-programming/060-promiseAll/es/README.md new file mode 100644 index 00000000..ec52c510 --- /dev/null +++ b/modules/60-asynchronous-programming/060-promiseAll/es/README.md @@ -0,0 +1,15 @@ +El método Promise.all permite ejecutar múltiples operaciones asíncronas en paralelo y obtener los resultados en cuanto se completen todas las tareas. + +Toma un array de promesas y devuelve una nueva promesa que: + +- Se resuelve en un array de resultados, en el mismo orden en que se pasaron las promesas; +- Se rechaza si al menos una de las promesas devuelve un error. + +Ejemplo: + +```js +const task = [fetch(url1), fetch(url2)]; +Promise.all(tasks).then((responses) => { + console.log(responses); // ambos resultados en el orden en que fueron llamados +}); +``` \ No newline at end of file diff --git a/modules/60-asynchronous-programming/060-promiseAll/es/data.yml b/modules/60-asynchronous-programming/060-promiseAll/es/data.yml new file mode 100644 index 00000000..41af3a08 --- /dev/null +++ b/modules/60-asynchronous-programming/060-promiseAll/es/data.yml @@ -0,0 +1,13 @@ +--- +name: Carga paralela +tips: + - > + [Promise.all](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Promise/all) + - > + [Promise](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Promise) + - > + [map](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Array/map) +definitions: + - name: Promise.all + description: | + Un método que permite ejecutar múltiples operaciones asíncronas en paralelo y esperar a que se completen. Los resultados se devuelven en el mismo orden en que se pasaron las promesas originales. diff --git a/modules/60-asynchronous-programming/060-promiseAll/index.js b/modules/60-asynchronous-programming/060-promiseAll/index.js new file mode 100644 index 00000000..233fdb93 --- /dev/null +++ b/modules/60-asynchronous-programming/060-promiseAll/index.js @@ -0,0 +1,10 @@ +import { downloadFile } from "./api"; + +// BEGIN +export const downloadAll = (files) => { + const tasks = files.map(downloadFile); + return Promise.all(tasks); +}; +// END + +export default downloadAll; \ No newline at end of file diff --git a/modules/60-asynchronous-programming/060-promiseAll/ru/EXERCISE.md b/modules/60-asynchronous-programming/060-promiseAll/ru/EXERCISE.md new file mode 100644 index 00000000..971d7b58 --- /dev/null +++ b/modules/60-asynchronous-programming/060-promiseAll/ru/EXERCISE.md @@ -0,0 +1,13 @@ +Реализуй функцию downloadAll(files), которая принимает массив имён файлов и возвращает промис, резолвящийся после загрузки всех файлов. + +Для загрузки одного файла используй уже готовую функцию downloadFile(fileName) - она возвращает промис. + +Функция downloadAll должна использовать Promise.all для параллельной загрузки всех файлов. + +Пример: + +```js +downloadAll(['1.txt', '2.txt']).then((result) => { + console.log(result); // ['1.txt loaded', '2.txt loaded'] +}); +``` \ No newline at end of file diff --git a/modules/60-asynchronous-programming/060-promiseAll/ru/README.md b/modules/60-asynchronous-programming/060-promiseAll/ru/README.md new file mode 100644 index 00000000..aac76f2b --- /dev/null +++ b/modules/60-asynchronous-programming/060-promiseAll/ru/README.md @@ -0,0 +1,15 @@ +Метод Promise.all позволяет запускать несколько асинхронных операций параллельно и получать результаты сразу после завершения всех задач. + +Он принимает массив промисов и возвращает новый промис, который: + +- Резолвится массивом результатов, в том же порядке, в каком были переданы промисы; +- Реджектится, если хотя бы один из промисов завершился с ошибкой. + +Пример: + +```js +const tasks = [fetch(url1), fetch(url2)]; +Promise.all(tasks).then((responses) => { + console.log(responses); // оба результата в порядке вызова +}); +``` \ No newline at end of file diff --git a/modules/60-asynchronous-programming/060-promiseAll/ru/data.yml b/modules/60-asynchronous-programming/060-promiseAll/ru/data.yml new file mode 100644 index 00000000..c957fc1e --- /dev/null +++ b/modules/60-asynchronous-programming/060-promiseAll/ru/data.yml @@ -0,0 +1,13 @@ +--- +name: Параллельная загрузка +tips: + - > + [Promise.all](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Promise/all) + - > + [Promise](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Promise) + - > + [map](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Array/map) +definitions: + - name: Promise.all + description: | + Метод, который позволяет запустить несколько асинхронных операций параллельно и дождаться, пока все они завершатся. Результаты приходят в том же порядке, в каком были переданы исходные промисы. diff --git a/modules/60-asynchronous-programming/060-promiseAll/test.js b/modules/60-asynchronous-programming/060-promiseAll/test.js new file mode 100644 index 00000000..970c006a --- /dev/null +++ b/modules/60-asynchronous-programming/060-promiseAll/test.js @@ -0,0 +1,22 @@ +import { describe, it, expect } from 'vitest'; +import f from './index.js'; + +describe('downloadAll', () => { + it('downloads all files in correct order', () => { + const files = ['file1.txt', 'file2.txt', 'file3.txt']; + + return f(files).then((result) => { + expect(result).toEqual([ + 'file1.txt loaded', + 'file2.txt loaded', + 'file3.txt loaded', + ]); + }); + }); + + it('works with empty array', () => { + return f([]).then((result) => { + expect(result).toEqual([]); + }); + }); +}); diff --git a/modules/60-asynchronous-programming/070-promises-final-test/Makefile b/modules/60-asynchronous-programming/070-promises-final-test/Makefile new file mode 100644 index 00000000..d0d0a48c --- /dev/null +++ b/modules/60-asynchronous-programming/070-promises-final-test/Makefile @@ -0,0 +1,2 @@ +test: + @ test.sh diff --git a/modules/60-asynchronous-programming/070-promises-final-test/api.js b/modules/60-asynchronous-programming/070-promises-final-test/api.js new file mode 100644 index 00000000..455d68d9 --- /dev/null +++ b/modules/60-asynchronous-programming/070-promises-final-test/api.js @@ -0,0 +1,39 @@ +const ordersDB = { + 1: { id: 1, paid: true, quantity: 2 }, + 2: { id: 2, paid: false, quantity: 5 }, + 3: { id: 3, paid: true, quantity: 150 }, +}; + +const fetchOrder = (id) => { + return new Promise((resolve) => { + setTimeout(() => { + resolve(ordersDB[id] || null); + }, 50); + }); +}; + +const validateOrder = (order) => { + return new Promise((resolve, reject) => { + if (!order.paid) { + reject(new Error('Order is not paid')); + } else if (order.quantity < 1 || order.quantity > 100) { + reject(new Error('Quantity must be between 1 and 100')); + } else { + resolve(order); + } + }); +}; + +const saveOrder = (order) => { + return new Promise((resolve) => { + setTimeout(() => { + resolve({ ...order, saved: true }); + }, 50); + }); +}; + +export { + fetchOrder, + validateOrder, + saveOrder, +} \ No newline at end of file diff --git a/modules/60-asynchronous-programming/070-promises-final-test/description.es.yml b/modules/60-asynchronous-programming/070-promises-final-test/description.es.yml new file mode 100644 index 00000000..20095e67 --- /dev/null +++ b/modules/60-asynchronous-programming/070-promises-final-test/description.es.yml @@ -0,0 +1,39 @@ +--- +name: Cesión final de promesas +theory: | + Las instrucciones asíncronas, los .then() anidados y la gestión de errores se suelen usar juntos. + + Un ejemplo de un flujo típico en aplicaciones reales: obtener datos, comprobar, guardar. + + Promise.then + Permite realizar una operación una vez completada la promesa. El valor de retorno se transmite a los siguientes pasos de la cadena. + + Promise.catch + Detecta errores en cualquiera de los .then anteriores. + + Combinando varios pasos + Las cadenas .then().then().then() permiten crear escenarios complejos: validación, comprobación de permisos, guardado, registro, etc. + + La capacidad de combinar promesas y generar y detectar errores correctamente es un aspecto importante del desarrollo. +instructions: | + Implementa una función getValidatedOrder(id) que: + + 1. Carga un pedido por id usando fetchOrder. + 2. Valida el pedido usando validateOrder: + - Si el pedido no se ha pagado, se debe generar el error "Order is not paid". + - Si la cantidad no está en el rango 1-100, se debe generar el error "Quantity must be between 1 and 100". + 3. Guarda el pedido usando saveOrder. + 4. Devuelve el resultado de guardar. + 5. Si no se encuentra el pedido, se genera el error "Order not found". + + Usa una cadena de .then(), throw y .catch(). +tips: + - > + [Promise](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Promise) + - > + [then](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Promise/then) + - > + [catch](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Promise/catch) +definitions: + - name: Fusión de promesas + description: Interacción paso a paso del resultado de una promesa a otra, con gestión centralizada de errores. diff --git a/modules/60-asynchronous-programming/070-promises-final-test/en/EXERCISE.md b/modules/60-asynchronous-programming/070-promises-final-test/en/EXERCISE.md new file mode 100644 index 00000000..c83efcad --- /dev/null +++ b/modules/60-asynchronous-programming/070-promises-final-test/en/EXERCISE.md @@ -0,0 +1,11 @@ +Implement a function getValidatedOrder(id) that: + +1. Loads an order by id using fetchOrder. +2. Validates the order using validateOrder: + - If the order is not paid, the error "Order is not paid" should be thrown. + - If the quantity is not in the range 1–100 - the error "Quantity must be between 1 and 100". +3. Saves the order using saveOrder. +4. Returns the result of saving. +5. If the order is not found - throws the error "Order not found". + +Use a chain of .then(), throw, .catch() \ No newline at end of file diff --git a/modules/60-asynchronous-programming/070-promises-final-test/en/README.md b/modules/60-asynchronous-programming/070-promises-final-test/en/README.md new file mode 100644 index 00000000..22b7194d --- /dev/null +++ b/modules/60-asynchronous-programming/070-promises-final-test/en/README.md @@ -0,0 +1,14 @@ +Asynchronous instructions, nested .then(), error handling are often used together. + +An example of a typical flow in real applications: get data, check, save. + +Promise.then +Allows you to perform an operation after the promise is completed. The return value is passed further down the chain. + +Promise.catch +Catches errors in any of the previous .then. + +Combining multiple steps +.then().then().then() chains allow you to build complex scenarios: validation, checking rights, saving, logging, etc. + +The ability to combine promises, correctly throw and catch errors is an important aspect in development. \ No newline at end of file diff --git a/modules/60-asynchronous-programming/070-promises-final-test/en/data.yml b/modules/60-asynchronous-programming/070-promises-final-test/en/data.yml new file mode 100644 index 00000000..e13e7126 --- /dev/null +++ b/modules/60-asynchronous-programming/070-promises-final-test/en/data.yml @@ -0,0 +1,12 @@ +--- +name: Final assignment of promises +tips: + - > + [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) + - > + [then](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then) + - > + [catch](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/catch) +definitions: + - name: Promise merging + description: Step-by-step interaction of the result from one then to another, with centralized error handling. diff --git a/modules/60-asynchronous-programming/070-promises-final-test/es/EXERCISE.md b/modules/60-asynchronous-programming/070-promises-final-test/es/EXERCISE.md new file mode 100644 index 00000000..5016f550 --- /dev/null +++ b/modules/60-asynchronous-programming/070-promises-final-test/es/EXERCISE.md @@ -0,0 +1,11 @@ +Implementa una función getValidatedOrder(id) que: + +1. Carga un pedido por id usando fetchOrder. +2. Valida el pedido usando validateOrder: + - Si el pedido no se ha pagado, se debe generar el error "Order is not paid". + - Si la cantidad no está en el rango 1-100, se debe generar el error "Quantity must be between 1 and 100". +3. Guarda el pedido usando saveOrder. +4. Devuelve el resultado de guardar. +5. Si no se encuentra el pedido, se genera el error "Order not found". + +Usa una cadena de .then(), throw y .catch(). \ No newline at end of file diff --git a/modules/60-asynchronous-programming/070-promises-final-test/es/README.md b/modules/60-asynchronous-programming/070-promises-final-test/es/README.md new file mode 100644 index 00000000..400626e9 --- /dev/null +++ b/modules/60-asynchronous-programming/070-promises-final-test/es/README.md @@ -0,0 +1,14 @@ +Las instrucciones asíncronas, los .then() anidados y la gestión de errores se suelen usar juntos. + +Un ejemplo de un flujo típico en aplicaciones reales: obtener datos, comprobar, guardar. + +Promise.then +Permite realizar una operación una vez completada la promesa. El valor de retorno se transmite a los siguientes pasos de la cadena. + +Promise.catch +Detecta errores en cualquiera de los .then anteriores. + +Combinando varios pasos +Las cadenas .then().then().then() permiten crear escenarios complejos: validación, comprobación de permisos, guardado, registro, etc. + +La capacidad de combinar promesas y generar y detectar errores correctamente es un aspecto importante del desarrollo. \ No newline at end of file diff --git a/modules/60-asynchronous-programming/070-promises-final-test/es/data.yml b/modules/60-asynchronous-programming/070-promises-final-test/es/data.yml new file mode 100644 index 00000000..c642bd89 --- /dev/null +++ b/modules/60-asynchronous-programming/070-promises-final-test/es/data.yml @@ -0,0 +1,12 @@ +--- +name: Cesión final de promesas +tips: + - > + [Promise](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Promise) + - > + [then](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Promise/then) + - > + [catch](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Promise/catch) +definitions: + - name: Fusión de promesas + description: Interacción paso a paso del resultado de una promesa a otra, con gestión centralizada de errores. diff --git a/modules/60-asynchronous-programming/070-promises-final-test/index.js b/modules/60-asynchronous-programming/070-promises-final-test/index.js new file mode 100644 index 00000000..24ee63c7 --- /dev/null +++ b/modules/60-asynchronous-programming/070-promises-final-test/index.js @@ -0,0 +1,18 @@ +import { fetchOrder, validateOrder, saveOrder } from "./api"; + +// BEGIN +export const getValidatedOrder = (id) => { + return fetchOrder(id) + .then((order) => { + if (!order) { + throw new Error('Order not found'); + } + return validateOrder(order); + }) + .then((validatedOrder) => { + return saveOrder(validatedOrder); + }); +}; +// END + +export default getValidatedOrder; diff --git a/modules/60-asynchronous-programming/070-promises-final-test/ru/EXERCISE.md b/modules/60-asynchronous-programming/070-promises-final-test/ru/EXERCISE.md new file mode 100644 index 00000000..0cce2e9e --- /dev/null +++ b/modules/60-asynchronous-programming/070-promises-final-test/ru/EXERCISE.md @@ -0,0 +1,11 @@ +Реализуйте функцию getValidatedOrder(id), которая: + +1. Загружает заказ по id с помощью fetchOrder. +2. Проверяет заказ с помощью validateOrder: + - Если заказ не оплачен, должна быть выброшена ошибка "Order is not paid". + - Если количество не входит в диапазон 1–100 - ошибка "Quantity must be between 1 and 100". +3. Сохраняет заказ с помощью saveOrder. +4. Возвращает результат сохранения. +5. Если заказ не найден - выбрасывает ошибку "Order not found". + +Используйте цепочку .then(), throw, .catch() \ No newline at end of file diff --git a/modules/60-asynchronous-programming/070-promises-final-test/ru/README.md b/modules/60-asynchronous-programming/070-promises-final-test/ru/README.md new file mode 100644 index 00000000..c01aa5de --- /dev/null +++ b/modules/60-asynchronous-programming/070-promises-final-test/ru/README.md @@ -0,0 +1,14 @@ +Асинхронные инструкции, вложенные .then(), обработку ошибок часто используют вместе. + +Пример типичного потока в реальных приложениях: получить данные, проверить, сохранить. + +Promise.then +Позволяет выполнить операцию после завершения промиса. Возвращаемое значение передаётся дальше по цепочке. + +Promise.catch +Отлавливает ошибки в любом из предыдущих .then. + +Объединение нескольких шагов +Цепочки .then().then().then() позволяют выстраивать сложные сценарии: валидация, проверка прав, сохранение, логирование и т.п. + +Умение комбинировать промисы, правильно выбрасывать и перехватывать ошибки - важный аспект при разработке. \ No newline at end of file diff --git a/modules/60-asynchronous-programming/070-promises-final-test/ru/data.yml b/modules/60-asynchronous-programming/070-promises-final-test/ru/data.yml new file mode 100644 index 00000000..7ececdca --- /dev/null +++ b/modules/60-asynchronous-programming/070-promises-final-test/ru/data.yml @@ -0,0 +1,12 @@ +--- +name: Финальная задание промисов +tips: + - > + [Promise](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Promise) + - > + [then](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Promise/then) + - > + [catch](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Promise/catch) +definitions: + - name: Объединение промисов + description: Поэтапная взаимодействие результата от одного then к другому, с централизованной обработкой ошибок. diff --git a/modules/60-asynchronous-programming/070-promises-final-test/test.js b/modules/60-asynchronous-programming/070-promises-final-test/test.js new file mode 100644 index 00000000..a7fb776a --- /dev/null +++ b/modules/60-asynchronous-programming/070-promises-final-test/test.js @@ -0,0 +1,32 @@ + +import { describe, it, expect } from 'vitest'; +import f from './index.js'; + +describe('getValidatedOrder', () => { + it('returns saved order with correct data', () => { + return f(1).then((result) => { + expect(result).toEqual({ id: 1, paid: true, quantity: 2, saved: true }); + }); + }); + + it('throws error if there is no order', () => { + return f(99).catch((error) => { + expect(error).toBeInstanceOf(Error); + expect(error.message).toBe('Order not found'); + }); + }); + + it('throws error when order is unpaid', () => { + return f(2).catch((error) => { + expect(error).toBeInstanceOf(Error); + expect(error.message).toBe('Order is not paid'); + }); + }); + + it('throws error if the quantity is invalid', () => { + return f(3).catch((error) => { + expect(error).toBeInstanceOf(Error); + expect(error.message).toBe('Quantity must be between 1 and 100'); + }); + }); +}); \ No newline at end of file diff --git a/modules/60-asynchronous-programming/080-async-await/Makefile b/modules/60-asynchronous-programming/080-async-await/Makefile new file mode 100644 index 00000000..d0d0a48c --- /dev/null +++ b/modules/60-asynchronous-programming/080-async-await/Makefile @@ -0,0 +1,2 @@ +test: + @ test.sh diff --git a/modules/60-asynchronous-programming/080-async-await/api.js b/modules/60-asynchronous-programming/080-async-await/api.js new file mode 100644 index 00000000..37d46048 --- /dev/null +++ b/modules/60-asynchronous-programming/080-async-await/api.js @@ -0,0 +1,26 @@ +const users = { + 1: { id: 1, name: 'Bran' }, + 2: { id: 2, name: 'Sansa' }, +}; + +const scores = { + 1: 120, + 2: 95, +}; + +const fetchUser = (id) => { + return new Promise((resolve) => { + setTimeout(() => resolve(users[id] ?? null), 100); + }); +}; + +const fetchScore = (user) => { + return new Promise((resolve) => { + setTimeout(() => resolve(scores[user.id] ?? 0), 100); + }); +}; + +export { + fetchUser, + fetchScore, +} \ No newline at end of file diff --git a/modules/60-asynchronous-programming/080-async-await/description.es.yml b/modules/60-asynchronous-programming/080-async-await/description.es.yml new file mode 100644 index 00000000..21b972b6 --- /dev/null +++ b/modules/60-asynchronous-programming/080-async-await/description.es.yml @@ -0,0 +1,69 @@ +--- +name: async/await +theory: | + Async y await son una forma moderna de trabajar con código asincrónico en JavaScript, lo que lo hace parecer síncrono y facilita su lectura y mantenimiento. + + - La palabra clave async se coloca antes de la declaración de la función. Esto convierte la función en asincrónica: siempre devuelve una promesa. + - Dentro de una función asíncrona, se puede usar el operador await, que pausa la lectura y la ejecución de nuevas instrucciones hasta que la promesa se cumpla donde se espera el resultado, si la lectura ya ha llegado al punto de usar el resultado de la promesa. + - Gracias a await, se puede escribir código asincrónico que se asemeja al código secuencial normal, sin devoluciones de llamadas anidadas ni cadenas .then(). + + ```js + Anteriormente, el código asincrónico solía verse así: + loadConfig() + .then(config => { + return connectToDB(config) + .then(db => { + return runQuery(db); + }); + }) + .then(result => { + console.log(result); + }) + .catch(err => { + console.error('Error:', err); + }); + Si hay muchas operaciones de este tipo, el código se anida y se vuelve difícil de leer; esto se conoce como la escalera del infierno. + + Lo mismo con async/await parece más sencillo: + async function runApp() { + try { + const config = await loadConfig(); + const db = await connectToDB(config); + const result = await runQuery(db); + console.log(result); + } catch (err) { + console.error('Error:', err); + } + } + + Este código es más fácil de leer porque parece código síncrono normal. + La gestión de errores también es más sencilla: basta con un try/catch normal. + ``` +instructions: | + Implementar la función formatUserInfo usando async/await. + + La función debe: + + 1. Obtener el usuario por ID usando fetchUser(id). + + 2. Si no se encuentra el usuario, generar un error con el mensaje "User not found". + + 3. Obtener los pedidos del usuario usando fetchOrders(user). + + 4. Devolver una cadena con el formato: "User: , Orders: ". + + Ejemplo: + ```js + await formatUserInfo(1); // 'Usuario: Jon, Pedidos: 2' + await formatUserInfo(42); // genera el error 'Usuario no encontrado' + ``` +tips: + - > + [async/await (MDN)](https://developer.mozilla.org/es/docs/Learn/JavaScript/Asynchronous/Async_await) + - > + [Error handling with try/catch](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Statements/try...catch) + - > + [Promise](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Promise) +definitions: + - name: async/await + description: Sintaxis que permite escribir código asincrónico de forma similar a la sincrónica, utilizando las palabras clave async y await. diff --git a/modules/60-asynchronous-programming/080-async-await/en/EXERCISE.md b/modules/60-asynchronous-programming/080-async-await/en/EXERCISE.md new file mode 100644 index 00000000..584999a3 --- /dev/null +++ b/modules/60-asynchronous-programming/080-async-await/en/EXERCISE.md @@ -0,0 +1,14 @@ +Implement the formatUserInfo function using async/await. + +The function should: + +1. Get the user by ID using fetchUser(id). +2. If the user is not found, throw an error with the message "User not found". +3. Get the user's orders using fetchOrders(user). +4. Return a string in the format: "User: , Orders: ". + +Example: +```js +await formatUserInfo(1); // 'User: Jon, Orders: 2' +await formatUserInfo(42); // throws an error 'User not found' +``` \ No newline at end of file diff --git a/modules/60-asynchronous-programming/080-async-await/en/README.md b/modules/60-asynchronous-programming/080-async-await/en/README.md new file mode 100644 index 00000000..7919dfc4 --- /dev/null +++ b/modules/60-asynchronous-programming/080-async-await/en/README.md @@ -0,0 +1,38 @@ +async and await are a modern way to work with asynchronous code in JavaScript, which makes it look like synchronous code and is much easier to read and maintain. + +- The async keyword is placed before the function declaration. This turns the function into an asynchronous one - it always returns a promise. +- Inside an async function, you can use the await operator - it pauses reading and execution of new instructions until the promise is fulfilled at the place where the result is expected, if reading has already reached the point of using the result of the promise. +- Thanks to await, you can write asynchronous code that looks like regular sequential code, without nested callbacks and .then() chains. + +```js +Previously, asynchronous code often looked like this: +loadConfig() + .then(config => { + return connectToDB(config) + .then(db => { + return runQuery(db); + }); + }) + .then(result => { + console.log(result); + }) + .catch(err => { + console.error('Error:', err); + }); +If there are many such operations, the code becomes nested and hard to read - this is called the stairs of hell + +The same with async/await looks simpler: +async function runApp() { + try { + const config = await loadConfig(); + const db = await connectToDB(config); + const result = await runQuery(db); + console.log(result); + } catch (err) { + console.error('Error:', err); + } +} + +This code is easier to read because it looks like regular synchronous code. +Error handling is also easier - a regular try/catch is enough. +``` \ No newline at end of file diff --git a/modules/60-asynchronous-programming/080-async-await/en/data.yml b/modules/60-asynchronous-programming/080-async-await/en/data.yml new file mode 100644 index 00000000..e7608991 --- /dev/null +++ b/modules/60-asynchronous-programming/080-async-await/en/data.yml @@ -0,0 +1,12 @@ +--- +name: async/await +tips: + - > + [async/await (MDN)](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Async_await) + - > + [Error handling with try/catch](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/try...catch) + - > + [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) +definitions: + - name: async/await + description: Syntax that allows writing asynchronous code in a form close to synchronous, using the async and await keywords. diff --git a/modules/60-asynchronous-programming/080-async-await/es/EXERCISE.md b/modules/60-asynchronous-programming/080-async-await/es/EXERCISE.md new file mode 100644 index 00000000..afe9942f --- /dev/null +++ b/modules/60-asynchronous-programming/080-async-await/es/EXERCISE.md @@ -0,0 +1,17 @@ +Implementar la función formatUserInfo usando async/await. + +La función debe: + +1. Obtener el usuario por ID usando fetchUser(id). + +2. Si no se encuentra el usuario, generar un error con el mensaje "User not found". + +3. Obtener los pedidos del usuario usando fetchOrders(user). + +4. Devolver una cadena con el formato: "User: , Orders: ". + +Ejemplo: +```js +await formatUserInfo(1); // 'Usuario: Jon, Pedidos: 2' +await formatUserInfo(42); // genera el error 'Usuario no encontrado' +``` \ No newline at end of file diff --git a/modules/60-asynchronous-programming/080-async-await/es/README.md b/modules/60-asynchronous-programming/080-async-await/es/README.md new file mode 100644 index 00000000..4079b091 --- /dev/null +++ b/modules/60-asynchronous-programming/080-async-await/es/README.md @@ -0,0 +1,38 @@ +Async y await son una forma moderna de trabajar con código asincrónico en JavaScript, lo que lo hace parecer síncrono y facilita su lectura y mantenimiento. + +- La palabra clave async se coloca antes de la declaración de la función. Esto convierte la función en asincrónica: siempre devuelve una promesa. +- Dentro de una función asíncrona, se puede usar el operador await, que pausa la lectura y la ejecución de nuevas instrucciones hasta que la promesa se cumpla donde se espera el resultado, si la lectura ya ha llegado al punto de usar el resultado de la promesa. +- Gracias a await, se puede escribir código asincrónico que se asemeja al código secuencial normal, sin devoluciones de llamadas anidadas ni cadenas .then(). + +```js +Anteriormente, el código asincrónico solía verse así: +loadConfig() + .then(config => { + return connectToDB(config) + .then(db => { + return runQuery(db); + }); + }) + .then(result => { + console.log(result); + }) + .catch(err => { + console.error('Error:', err); + }); +Si hay muchas operaciones de este tipo, el código se anida y se vuelve difícil de leer; esto se conoce como la escalera del infierno. + +Lo mismo con async/await parece más sencillo: +async function runApp() { + try { + const config = await loadConfig(); + const db = await connectToDB(config); + const result = await runQuery(db); + console.log(result); + } catch (err) { + console.error('Error:', err); + } +} + +Este código es más fácil de leer porque parece código síncrono normal. +La gestión de errores también es más sencilla: basta con un try/catch normal. +``` \ No newline at end of file diff --git a/modules/60-asynchronous-programming/080-async-await/es/data.yml b/modules/60-asynchronous-programming/080-async-await/es/data.yml new file mode 100644 index 00000000..4ddb3333 --- /dev/null +++ b/modules/60-asynchronous-programming/080-async-await/es/data.yml @@ -0,0 +1,12 @@ +--- +name: async/await +tips: + - > + [async/await (MDN)](https://developer.mozilla.org/es/docs/Learn/JavaScript/Asynchronous/Async_await) + - > + [Error handling with try/catch](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Statements/try...catch) + - > + [Promise](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Promise) +definitions: + - name: async/await + description: Sintaxis que permite escribir código asincrónico de forma similar a la sincrónica, utilizando las palabras clave async y await. diff --git a/modules/60-asynchronous-programming/080-async-await/index.js b/modules/60-asynchronous-programming/080-async-await/index.js new file mode 100644 index 00000000..999957e3 --- /dev/null +++ b/modules/60-asynchronous-programming/080-async-await/index.js @@ -0,0 +1,13 @@ +import { fetchUser, fetchScore } from "./api"; + +// BEGIN +const formatUserInfo = async (id) => { + const user = await fetchUser(id); + if (!user) throw new Error('User not found'); + const score = await fetchScore(user); + return `Name: ${user.name}, Score: ${score}`; +}; +// END + +export default formatUserInfo; + diff --git a/modules/60-asynchronous-programming/080-async-await/ru/EXERCISE.md b/modules/60-asynchronous-programming/080-async-await/ru/EXERCISE.md new file mode 100644 index 00000000..df90e5c5 --- /dev/null +++ b/modules/60-asynchronous-programming/080-async-await/ru/EXERCISE.md @@ -0,0 +1,14 @@ +Реализуйте функцию formatUserInfo, используя async/await. + +Функция должна: + +1. Получать пользователя по идентификатору с помощью fetchUser(id). +2. Если пользователь не найден — выбрасывать ошибку с сообщением "User not found". +3. Получать заказы пользователя через fetchOrders(user). +4. Возвращать строку в формате: "User: <имя>, Orders: <кол-во заказов>". + +Пример: +```js +await formatUserInfo(1); // 'User: Jon, Orders: 2' +await formatUserInfo(42); // выбрасывает ошибку 'User not found' +``` \ No newline at end of file diff --git a/modules/60-asynchronous-programming/080-async-await/ru/README.md b/modules/60-asynchronous-programming/080-async-await/ru/README.md new file mode 100644 index 00000000..11405a2a --- /dev/null +++ b/modules/60-asynchronous-programming/080-async-await/ru/README.md @@ -0,0 +1,38 @@ +async и await - это современный способ работать с асинхронным кодом в JavaScript, который делает его похожим на синхронный и значительно упрощает чтение и поддержку. + +- Ключевое слово async ставится перед объявлением функции. Это превращает функцию в асинхронную - она всегда возвращает промис. +- Внутри async функции можно использовать оператор await - он приостанавливает чтение и выполнение новых инструкций до тех пор, пока промис не выполнится в месте ожидания результата, если чтение уже дошло до момента использования результата промиса. +- Благодаря await можно писать асинхронный код, который выглядит как обычный последовательный, без вложенных колбеков и цепочек .then(). + +```js +Раньше асинхронный код часто выглядел так: +loadConfig() + .then(config => { + return connectToDB(config) + .then(db => { + return runQuery(db); + }); + }) + .then(result => { + console.log(result); + }) + .catch(err => { + console.error('Error:', err); + }); +Если таких операций много, код становится вложенным и трудночитаемым - это называют лестницей ада + +То же самое с async/await выглядит проще: +async function runApp() { + try { + const config = await loadConfig(); + const db = await connectToDB(config); + const result = await runQuery(db); + console.log(result); + } catch (err) { + console.error('Error:', err); + } +} + +Такой код легче читать, потому что он похож на обычный синхронный. +Управление ошибками также проще - достаточно обычного try/catch. +``` \ No newline at end of file diff --git a/modules/60-asynchronous-programming/080-async-await/ru/data.yml b/modules/60-asynchronous-programming/080-async-await/ru/data.yml new file mode 100644 index 00000000..6684a104 --- /dev/null +++ b/modules/60-asynchronous-programming/080-async-await/ru/data.yml @@ -0,0 +1,12 @@ +--- +name: async/await +tips: + - > + [async/await (MDN)](https://developer.mozilla.org/ru/docs/Learn/JavaScript/Asynchronous/Async_await) + - > + [Error handling with try/catch](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Statements/try...catch) + - > + [Promise](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Promise) +definitions: + - name: async/await + description: Синтаксис, позволяющий писать асинхронный код в виде, близком к синхронному, с использованием ключевых слов async и await. diff --git a/modules/60-asynchronous-programming/080-async-await/test.js b/modules/60-asynchronous-programming/080-async-await/test.js new file mode 100644 index 00000000..19e42869 --- /dev/null +++ b/modules/60-asynchronous-programming/080-async-await/test.js @@ -0,0 +1,18 @@ +import { describe, it, expect } from 'vitest'; +import f from './index.js'; + +describe('formatUserInfo', () => { + it('returns formatted string for existing user', async () => { + const result = await f(1); + expect(result).toBe('Name: Bran, Score: 120'); + }); + + it('returns formatted string for another user', async () => { + const result = await f(2); + expect(result).toBe('Name: Sansa, Score: 95'); + }); + + it('throws error if user not found', async () => { + await expect(f(3)).rejects.toThrow('User not found'); + }); +}); \ No newline at end of file diff --git a/modules/60-asynchronous-programming/090-async-catch/Makefile b/modules/60-asynchronous-programming/090-async-catch/Makefile new file mode 100644 index 00000000..d0d0a48c --- /dev/null +++ b/modules/60-asynchronous-programming/090-async-catch/Makefile @@ -0,0 +1,2 @@ +test: + @ test.sh diff --git a/modules/60-asynchronous-programming/090-async-catch/api.js b/modules/60-asynchronous-programming/090-async-catch/api.js new file mode 100644 index 00000000..5d11cff4 --- /dev/null +++ b/modules/60-asynchronous-programming/090-async-catch/api.js @@ -0,0 +1,18 @@ +async function fetchCityWeatherList() { + return [ + { city: 'Madrid', temp: 30 }, + { city: 'Oslo', temp: 12 }, + { city: 'Cairo', temp: 36 }, + { city: 'London', temp: 20 }, + { city: 'Bangkok', temp: 34 }, + ]; +} + +async function postToSocial(text) { + return `Successfully posted. ${text}`; +} + +export { + fetchCityWeatherList, + postToSocial, +} \ No newline at end of file diff --git a/modules/60-asynchronous-programming/090-async-catch/description.es.yml b/modules/60-asynchronous-programming/090-async-catch/description.es.yml new file mode 100644 index 00000000..e5fc870a --- /dev/null +++ b/modules/60-asynchronous-programming/090-async-catch/description.es.yml @@ -0,0 +1,55 @@ +--- +name: Informe de Ciudades Destacadas +theory: | + Cuando se produce un error en una función asíncrona, la promesa se rechaza. Para detectar estos errores, se utiliza try/catch. + + ```js + async function fetchData() { + try { + const result = await fetchSomeData(); + return result; + } catch (error) { + return error.message; + } + } + ``` +instructions: | + Implementa una función postHotCitiesReport que: + + 1. Obtiene un array de ciudades con temperaturas usando fetchCityWeatherList() + 2. Conserva solo aquellas con temperaturas superiores a 25 °C + 3. Genera el texto "Hot cities today:" with a list of such cities, or the string "No hot cities today." si no hay ninguna + 4. Publica el texto usando postToSocial() + 5. Si se produce un error en cualquier paso, devuelve err.message + + Usa async/await y una construcción try/catch. + + Ejemplo: + + ```js + // Si se recibió y publicó correctamente: + postHotCitiesReport() + .then(console.log); //Posible resultado: "Successfully posted. Hot cities today: Madrid, Cairo, Bangkok" + + // Si no hay ciudades con temperaturas superiores a 25: + postHotCitiesReport() + .then(console.log); // "Successfully posted. No hot cities today." + + // Error al cargar datos: + postHotCitiesReport() + .then(console.log); // "Failed to load city weather list" + + // Error al publicar: + postHotCitiesReport() + .then(console.log); // "Failed to post to social network" + ``` +tips: + - > + [async function](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Statements/async_function) + - > + [await](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Operators/await) + - > + [try...catch](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Statements/try...catch) +definitions: + - name: try/catch + description: Permite detectar errores en funciones asíncronas, lo que hace que el código sea fiable y lineal. diff --git a/modules/60-asynchronous-programming/090-async-catch/en/EXERCISE.md b/modules/60-asynchronous-programming/090-async-catch/en/EXERCISE.md new file mode 100644 index 00000000..f151c168 --- /dev/null +++ b/modules/60-asynchronous-programming/090-async-catch/en/EXERCISE.md @@ -0,0 +1,29 @@ +Implement a postHotCitiesReport function that: + +1. Gets an array of cities with temperatures using fetchCityWeatherList() +2. Keeps only those with temperatures above 25°C +3. Generates the text "Hot cities today:" with a list of such cities, or the string "No hot cities today." if there are none +4. Publishes the text using postToSocial() +5. If an error occurs at any step, returns err.message + +Use async/await and a try/catch construct. + +Example: + +```js +// If successfully received and published: +postHotCitiesReport() + .then(console.log); //Possible output: "Successfully posted. Hot cities today: Madrid, Cairo, Bangkok" + +// If there are no cities with temperatures above 25: +postHotCitiesReport() + .then(console.log); // "Successfully posted. No hot cities today." + +// On data loading error: +postHotCitiesReport() + .then(console.log); // "Failed to load city weather list" + +// On publishing error: +postHotCitiesReport() + .then(console.log); // "Failed to post to social network" +``` \ No newline at end of file diff --git a/modules/60-asynchronous-programming/090-async-catch/en/README.md b/modules/60-asynchronous-programming/090-async-catch/en/README.md new file mode 100644 index 00000000..08b2ceb3 --- /dev/null +++ b/modules/60-asynchronous-programming/090-async-catch/en/README.md @@ -0,0 +1,12 @@ +When an error occurs in an async function, it causes the promise to be rejected. To catch such errors, try/catch is used. + +```js +async function fetchData() { + try { + const result = await fetchSomeData(); + return result; + } catch (error) { + return error.message; + } +} +``` \ No newline at end of file diff --git a/modules/60-asynchronous-programming/090-async-catch/en/data.yml b/modules/60-asynchronous-programming/090-async-catch/en/data.yml new file mode 100644 index 00000000..7544b8ef --- /dev/null +++ b/modules/60-asynchronous-programming/090-async-catch/en/data.yml @@ -0,0 +1,12 @@ +--- +name: Hot Cities Report +tips: + - > + [async function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function) + - > + [await](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await) + - > + [try...catch](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/try...catch) +definitions: + - name: try/catch + description: Allows you to catch errors in async functions, making the code reliable and linear. diff --git a/modules/60-asynchronous-programming/090-async-catch/es/EXERCISE.md b/modules/60-asynchronous-programming/090-async-catch/es/EXERCISE.md new file mode 100644 index 00000000..10ab067b --- /dev/null +++ b/modules/60-asynchronous-programming/090-async-catch/es/EXERCISE.md @@ -0,0 +1,29 @@ +Implementa una función postHotCitiesReport que: + +1. Obtiene un array de ciudades con temperaturas usando fetchCityWeatherList() +2. Conserva solo aquellas con temperaturas superiores a 25 °C +3. Genera el texto "Hot cities today:" with a list of such cities, or the string "No hot cities today." si no hay ninguna +4. Publica el texto usando postToSocial() +5. Si se produce un error en cualquier paso, devuelve err.message + +Usa async/await y una construcción try/catch. + +Ejemplo: + +```js +// Si se recibió y publicó correctamente: +postHotCitiesReport() + .then(console.log); //Posible resultado: "Successfully posted. Hot cities today: Madrid, Cairo, Bangkok" + +// Si no hay ciudades con temperaturas superiores a 25: +postHotCitiesReport() + .then(console.log); // "Successfully posted. No hot cities today." + +// Error al cargar datos: +postHotCitiesReport() + .then(console.log); // "Failed to load city weather list" + +// Error al publicar: +postHotCitiesReport() + .then(console.log); // "Failed to post to social network" +``` \ No newline at end of file diff --git a/modules/60-asynchronous-programming/090-async-catch/es/README.md b/modules/60-asynchronous-programming/090-async-catch/es/README.md new file mode 100644 index 00000000..1348ef6b --- /dev/null +++ b/modules/60-asynchronous-programming/090-async-catch/es/README.md @@ -0,0 +1,12 @@ +Cuando se produce un error en una función asíncrona, la promesa se rechaza. Para detectar estos errores, se utiliza try/catch. + +```js +async function fetchData() { + try { + const result = await fetchSomeData(); + return result; + } catch (error) { + return error.message; + } +} +``` \ No newline at end of file diff --git a/modules/60-asynchronous-programming/090-async-catch/es/data.yml b/modules/60-asynchronous-programming/090-async-catch/es/data.yml new file mode 100644 index 00000000..4c84fefa --- /dev/null +++ b/modules/60-asynchronous-programming/090-async-catch/es/data.yml @@ -0,0 +1,12 @@ +--- +name: Informe de Ciudades Destacadas +tips: + - > + [async function](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Statements/async_function) + - > + [await](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Operators/await) + - > + [try...catch](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Statements/try...catch) +definitions: + - name: try/catch + description: Permite detectar errores en funciones asíncronas, lo que hace que el código sea fiable y lineal. diff --git a/modules/60-asynchronous-programming/090-async-catch/index.js b/modules/60-asynchronous-programming/090-async-catch/index.js new file mode 100644 index 00000000..933cc203 --- /dev/null +++ b/modules/60-asynchronous-programming/090-async-catch/index.js @@ -0,0 +1,21 @@ +import { fetchCityWeatherList, postToSocial} from './api.js'; + +// BEGIN +async function postHotCitiesReport() { + try { + const cities = await fetchCityWeatherList(); + const hotCities = cities.filter(({ temp }) => temp > 25).map(({ city }) => city); + + const text = hotCities.length + ? `Hot cities today: ${hotCities.join(', ')}` + : 'No hot cities today.'; + + const result = await postToSocial(text); + return result; + } catch (err) { + return err.message; + } +} +// END + +export default postHotCitiesReport; \ No newline at end of file diff --git a/modules/60-asynchronous-programming/090-async-catch/ru/EXERCISE.md b/modules/60-asynchronous-programming/090-async-catch/ru/EXERCISE.md new file mode 100644 index 00000000..9a4d4473 --- /dev/null +++ b/modules/60-asynchronous-programming/090-async-catch/ru/EXERCISE.md @@ -0,0 +1,29 @@ +Реализуйте функцию postHotCitiesReport, которая: + +1. Получает массив городов с температурой с помощью fetchCityWeatherList() +2. Оставляет только те, где температура больше 25°C +3. Формирует текст "Hot cities today:" с перечислением таких городов, либо строку "No hot cities today.", если таких нет +4. Публикует текст через postToSocial() +5. Если возникает ошибка на любом шаге — возвращает err.message + +Используйте async/await и конструкцию try/catch. + +Пример: + +```js +// При успешном получении и публикации: +postHotCitiesReport() + .then(console.log); //Возможный вывод: "Successfully posted. Hot cities today: Madrid, Cairo, Bangkok" + +// Если нет городов с температурой выше 25: +postHotCitiesReport() + .then(console.log); // "Successfully posted. No hot cities today." + +// При ошибке загрузки данных: +postHotCitiesReport() + .then(console.log); // "Failed to load city weather list" + +// При ошибке публикации: +postHotCitiesReport() + .then(console.log); // "Failed to post to social network" +``` \ No newline at end of file diff --git a/modules/60-asynchronous-programming/090-async-catch/ru/README.md b/modules/60-asynchronous-programming/090-async-catch/ru/README.md new file mode 100644 index 00000000..3893c3f9 --- /dev/null +++ b/modules/60-asynchronous-programming/090-async-catch/ru/README.md @@ -0,0 +1,12 @@ +Когда в async функции происходит ошибка, она вызывает отклонение промиса (reject). Чтобы перехватывать такие ошибки, используется try/catch. + +```js +async function fetchData() { + try { + const result = await fetchSomeData(); + return result; + } catch (error) { + return error.message; + } +} +``` \ No newline at end of file diff --git a/modules/60-asynchronous-programming/090-async-catch/ru/data.yml b/modules/60-asynchronous-programming/090-async-catch/ru/data.yml new file mode 100644 index 00000000..a403e389 --- /dev/null +++ b/modules/60-asynchronous-programming/090-async-catch/ru/data.yml @@ -0,0 +1,12 @@ +--- +name: Отчёт о жарких городах +tips: + - > + [async function](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Statements/async_function) + - > + [await](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Operators/await) + - > + [try...catch](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Statements/try...catch) +definitions: + - name: try/catch + description: Позволяет перехватывать ошибки в async-функциях, делая код надёжным и линейным. diff --git a/modules/60-asynchronous-programming/090-async-catch/test.js b/modules/60-asynchronous-programming/090-async-catch/test.js new file mode 100644 index 00000000..695bd066 --- /dev/null +++ b/modules/60-asynchronous-programming/090-async-catch/test.js @@ -0,0 +1,43 @@ +import { describe, it, expect, vi } from 'vitest'; +import * as api from './api.js' +import f from './index.js'; + +describe('postHotCitiesReport', () => { + it('posts list of hot cities', async () => { + const result = await f(); + expect(result).toMatch(/Successfully posted. Hot cities today:/); + expect(result).toContain('Madrid'); + expect(result).toContain('Cairo'); + expect(result).toContain('Bangkok'); + }); + + it('handles no hot cities', async () => { + vi.spyOn(api, 'fetchCityWeatherList').mockResolvedValue([ + { city: 'Reykjavik', temp: 5 }, + { city: 'Oslo', temp: 10 }, + ]); + + const result = await f(); + expect(result).toContain('No hot cities'); + + vi.restoreAllMocks(); + }); + + it('handles fetch failure', async () => { + vi.spyOn(api, 'fetchCityWeatherList').mockRejectedValue(new Error('Failed to load city weather list')); + + const result = await f(); + expect(result).toBe('Failed to load city weather list'); + + vi.restoreAllMocks(); + }); + + it('handles post failure', async () => { + vi.spyOn(api, 'postToSocial').mockRejectedValue(new Error('Failed to post to social network')); + + const result = await f(); + expect(result).toBe('Failed to post to social network'); + + vi.restoreAllMocks(); + }); +}); \ No newline at end of file diff --git a/modules/60-asynchronous-programming/100-async-final-test/Makefile b/modules/60-asynchronous-programming/100-async-final-test/Makefile new file mode 100644 index 00000000..d0d0a48c --- /dev/null +++ b/modules/60-asynchronous-programming/100-async-final-test/Makefile @@ -0,0 +1,2 @@ +test: + @ test.sh diff --git a/modules/60-asynchronous-programming/100-async-final-test/api.js b/modules/60-asynchronous-programming/100-async-final-test/api.js new file mode 100644 index 00000000..661408f1 --- /dev/null +++ b/modules/60-asynchronous-programming/100-async-final-test/api.js @@ -0,0 +1,15 @@ +export async function getUser(id) { + return { id, name: 'Имя Пользователя' }; +} + +export async function getEmail(user) { + return `${user.name.toLowerCase()}@example.com`; +} + +export async function prepareMessage(email) { + return `Send notification to ${email}`; +} + +export async function sendNotification(message) { + console.log('Notification sent:', message); +} \ No newline at end of file diff --git a/modules/60-asynchronous-programming/100-async-final-test/description.es.yml b/modules/60-asynchronous-programming/100-async-final-test/description.es.yml new file mode 100644 index 00000000..5a16b28c --- /dev/null +++ b/modules/60-asynchronous-programming/100-async-final-test/description.es.yml @@ -0,0 +1,48 @@ +--- +name: Notificar sobre usuarios inactivos +theory: | + ```js + // Cuando se necesitan ejecutar varios pasos asincrónicos en orden, + // es conveniente usar la palabra clave await dentro de una función asíncrona. + + async function doSteps() { + try { + const result1 = await firstStep(); + const result2 = await secondStep(result1); + const result3 = await thirdStep(result2); + return result3; + } catch (__error) { + // Si alguna de las operaciones genera un error, se llamará al bloque catch. + return `An error happened: ${__error}`; + } + } + ``` +instructions: | + En esta tarea, las funciones se importan mediante la API. + + Implementar la función notifyAboutInactive(userId) debe realizar una cadena de pasos asíncronos: + + 1. Obtener el usuario mediante getUser(userId) + 2. Obtener el correo electrónico de este usuario mediante getEmail(user) + 3. Preparar el mensaje: prepareMessage(email) + 4. Enviar la notificación: sendNotification(message) + + Si todos los pasos se realizaron correctamente, la función debe devolver la cadena "OK". + + Si se produce un error en cualquier etapa, devolver la cadena "FAIL". + + Para la implementación, utilice async/await y la gestión de errores mediante try/catch. +tips: + - > + [async function](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Statements/async_function) + - > + [await](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Operators/await) + - > + [try...catch](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Statements/try...catch) +definitions: + - name: async function + description: Palabra clave para declarar una función asíncrona que devuelve una promesa. + - name: await + description: Permite pausar la ejecución de una función asíncrona hasta que se resuelva la promesa y se obtenga su resultado. + - name: try/catch + description: Una constante para gestionar errores en un bloque try y capturar excepciones en un catch, especialmente útil en async/await. diff --git a/modules/60-asynchronous-programming/100-async-final-test/en/EXERCISE.md b/modules/60-asynchronous-programming/100-async-final-test/en/EXERCISE.md new file mode 100644 index 00000000..6015386b --- /dev/null +++ b/modules/60-asynchronous-programming/100-async-final-test/en/EXERCISE.md @@ -0,0 +1,14 @@ +In this task, functions are imported via api + +Implement the function notifyAboutInactive(userId) should perform a chain of asynchronous steps: + +1. Get the user using getUser(userId) +2. Get the email of this user via getEmail(user) +3. Prepare the message: prepareMessage(email) +4. Send the notification: sendNotification(message) + +If all steps were successful, the function should return the string 'OK'. + +If an error occurred at any stage, return the string 'FAIL'. + +For implementation, use async/await and error handling via try/catch. \ No newline at end of file diff --git a/modules/60-asynchronous-programming/100-async-final-test/en/README.md b/modules/60-asynchronous-programming/100-async-final-test/en/README.md new file mode 100644 index 00000000..0113f8c5 --- /dev/null +++ b/modules/60-asynchronous-programming/100-async-final-test/en/README.md @@ -0,0 +1,16 @@ +```js +// When you need to execute several asynchronous steps in order, +// it is convenient to use the await keyword inside an async function. + +async function doSteps() { + try { + const result1 = await firstStep(); + const result2 = await secondStep(result1); + const result3 = await thirdStep(result2); + return result3; + } catch (__error) { + // If any of the operations throws an error, then the catch block will be called. + return `An error happened: ${__error}`; + } +} +``` \ No newline at end of file diff --git a/modules/60-asynchronous-programming/100-async-final-test/en/data.yml b/modules/60-asynchronous-programming/100-async-final-test/en/data.yml new file mode 100644 index 00000000..3393ba4b --- /dev/null +++ b/modules/60-asynchronous-programming/100-async-final-test/en/data.yml @@ -0,0 +1,16 @@ +--- +name: Notify about inactive users +tips: + - > + [async function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function) + - > + [await](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await) + - > + [try...catch](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/try...catch) +definitions: + - name: async function + description: Keyword for declaring an asynchronous function that returns a promise. + - name: await + description: Allows you to pause the execution of an async function until the promise is resolved and get its result. + - name: try/catch + description: A consten-USct for handling errors in a try block and catching exceptions in a catch, especially useful in async/await. diff --git a/modules/60-asynchronous-programming/100-async-final-test/es/EXERCISE.md b/modules/60-asynchronous-programming/100-async-final-test/es/EXERCISE.md new file mode 100644 index 00000000..a9845c05 --- /dev/null +++ b/modules/60-asynchronous-programming/100-async-final-test/es/EXERCISE.md @@ -0,0 +1,14 @@ +En esta tarea, las funciones se importan mediante la API. + +Implementar la función notifyAboutInactive(userId) debe realizar una cadena de pasos asíncronos: + +1. Obtener el usuario mediante getUser(userId) +2. Obtener el correo electrónico de este usuario mediante getEmail(user) +3. Preparar el mensaje: prepareMessage(email) +4. Enviar la notificación: sendNotification(message) + +Si todos los pasos se realizaron correctamente, la función debe devolver la cadena "OK". + +Si se produce un error en cualquier etapa, devolver la cadena "FAIL". + +Para la implementación, utilice async/await y la gestión de errores mediante try/catch. \ No newline at end of file diff --git a/modules/60-asynchronous-programming/100-async-final-test/es/README.md b/modules/60-asynchronous-programming/100-async-final-test/es/README.md new file mode 100644 index 00000000..f14e5a0b --- /dev/null +++ b/modules/60-asynchronous-programming/100-async-final-test/es/README.md @@ -0,0 +1,16 @@ +```js +// Cuando se necesitan ejecutar varios pasos asincrónicos en orden, +// es conveniente usar la palabra clave await dentro de una función asíncrona. + +async function doSteps() { + try { + const result1 = await firstStep(); + const result2 = await secondStep(result1); + const result3 = await thirdStep(result2); + return result3; + } catch (__error) { + // Si alguna de las operaciones genera un error, se llamará al bloque catch. + return `An error happened: ${__error}`; + } +} +``` \ No newline at end of file diff --git a/modules/60-asynchronous-programming/100-async-final-test/es/data.yml b/modules/60-asynchronous-programming/100-async-final-test/es/data.yml new file mode 100644 index 00000000..327788b2 --- /dev/null +++ b/modules/60-asynchronous-programming/100-async-final-test/es/data.yml @@ -0,0 +1,16 @@ +--- +name: Notificar sobre usuarios inactivos +tips: + - > + [async function](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Statements/async_function) + - > + [await](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Operators/await) + - > + [try...catch](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Statements/try...catch) +definitions: + - name: async function + description: Palabra clave para declarar una función asíncrona que devuelve una promesa. + - name: await + description: Permite pausar la ejecución de una función asíncrona hasta que se resuelva la promesa y se obtenga su resultado. + - name: try/catch + description: Una constante para gestionar errores en un bloque try y capturar excepciones en un catch, especialmente útil en async/await. diff --git a/modules/60-asynchronous-programming/100-async-final-test/index.js b/modules/60-asynchronous-programming/100-async-final-test/index.js new file mode 100644 index 00000000..65460e78 --- /dev/null +++ b/modules/60-asynchronous-programming/100-async-final-test/index.js @@ -0,0 +1,17 @@ +import * as api from './api.js'; + +// BEGIN +export async function notifyAboutInactive(userId) { + try { + const user = await api.getUser(userId); + const email = await api.getEmail(user); + const message = await api.prepareMessage(email); + await api.sendNotification(message); + return 'OK'; + } catch { + return 'FAIL'; + } +} +// END + +export default notifyAboutInactive; \ No newline at end of file diff --git a/modules/60-asynchronous-programming/100-async-final-test/ru/EXERCISE.md b/modules/60-asynchronous-programming/100-async-final-test/ru/EXERCISE.md new file mode 100644 index 00000000..497d7120 --- /dev/null +++ b/modules/60-asynchronous-programming/100-async-final-test/ru/EXERCISE.md @@ -0,0 +1,14 @@ +В этом задании функции импортированы через api + +Реализуйте функцию notifyAboutInactive(userId) должна выполнять цепочку асинхронных шагов: + +1. Получить пользователя с помощью getUser(userId) +2. Получить email этого пользователя через getEmail(user) +3. Подготовить сообщение: prepareMessage(email) +4. Отправить уведомление: sendNotification(message) + +Если все шаги прошли успешно, функция должна вернуть строку 'OK'. + +Если на любом этапе произошла ошибка - вернуть строку 'FAIL'. + +Для реализации следует использовать async/await и обработку ошибок через try/catch. \ No newline at end of file diff --git a/modules/60-asynchronous-programming/100-async-final-test/ru/README.md b/modules/60-asynchronous-programming/100-async-final-test/ru/README.md new file mode 100644 index 00000000..c6aa1521 --- /dev/null +++ b/modules/60-asynchronous-programming/100-async-final-test/ru/README.md @@ -0,0 +1,16 @@ +```js +// Когда нужно выполнить несколько асинхронных шагов по порядку, +// удобно использовать ключевое слово await внутри async-функции. + +async function doSteps() { + try { + const result1 = await firstStep(); + const result2 = await secondStep(result1); + const result3 = await thirdStep(result2); + return result3; + } catch (__error) { + // Если любая из операций выбросит ошибку, тогда вызовется блок catch + return `An error happened: ${__error}`; + } +} +``` \ No newline at end of file diff --git a/modules/60-asynchronous-programming/100-async-final-test/ru/data.yml b/modules/60-asynchronous-programming/100-async-final-test/ru/data.yml new file mode 100644 index 00000000..19004373 --- /dev/null +++ b/modules/60-asynchronous-programming/100-async-final-test/ru/data.yml @@ -0,0 +1,16 @@ +--- +name: Уведомление об неактивных пользователях +tips: + - > + [async function](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Statements/async_function) + - > + [await](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Operators/await) + - > + [try...catch](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Statements/try...catch) +definitions: + - name: async function + description: Ключевое слово для объявления асинхронной функции, которая возвращает промис. + - name: await + description: Позволяет приостановить выполнение async-функции до разрешения промиса и получить его результат. + - name: try/catch + description: Конструкция для обработки ошибок в блоке try и перехвата исключений в catch, особенно полезна в async/await. diff --git a/modules/60-asynchronous-programming/100-async-final-test/test.js b/modules/60-asynchronous-programming/100-async-final-test/test.js new file mode 100644 index 00000000..115893a9 --- /dev/null +++ b/modules/60-asynchronous-programming/100-async-final-test/test.js @@ -0,0 +1,36 @@ +import { describe, it, expect, vi, afterEach } from 'vitest'; +import * as api from './api.js'; +import notifyAboutInactive from './index.js'; + +describe('notifyAboutInactive', () => { + afterEach(() => { + vi.restoreAllMocks(); + }); + + it('successfully sends notification', async () => { + vi.spyOn(api, 'getUser').mockResolvedValue({ id: 1, name: 'TestUser' }); + vi.spyOn(api, 'getEmail').mockResolvedValue('testuser@example.com'); + vi.spyOn(api, 'prepareMessage').mockResolvedValue('Hello, testuser@example.com'); + vi.spyOn(api, 'sendNotification').mockResolvedValue(true); + + const result = await notifyAboutInactive(1); + expect(result).toBe('OK'); + }); + + it('returns FAIL on error in getUser', async () => { + vi.spyOn(api, 'getUser').mockRejectedValue(new Error('fail')); + + const result = await notifyAboutInactive(1); + expect(result).toBe('FAIL'); + }); + + it('returns FAIL on error in sendNotification', async () => { + vi.spyOn(api, 'getUser').mockResolvedValue({ id: 1, name: 'TestUser' }); + vi.spyOn(api, 'getEmail').mockResolvedValue('testuser@example.com'); + vi.spyOn(api, 'prepareMessage').mockResolvedValue('Hello, testuser@example.com'); + vi.spyOn(api, 'sendNotification').mockRejectedValue(new Error('fail')); + + const result = await notifyAboutInactive(1); + expect(result).toBe('FAIL'); + }); +}); \ No newline at end of file diff --git a/modules/60-asynchronous-programming/description.en.yml b/modules/60-asynchronous-programming/description.en.yml new file mode 100644 index 00000000..3f48ff2d --- /dev/null +++ b/modules/60-asynchronous-programming/description.en.yml @@ -0,0 +1,8 @@ +--- + +name: Asynchronous programming +description: | + There are often situations in programming where the execution of an instruction needs to be delayed or delegated to another part of the code. + Instead of waiting for a task to complete, the program can continue performing other operations while monitoring the status of the asynchronous task separately. + + Asyncronism allows for efficient execution time management, especially when dealing with latency, network requests, and I/O operations. diff --git a/modules/60-asynchronous-programming/description.es.yml b/modules/60-asynchronous-programming/description.es.yml new file mode 100644 index 00000000..5d276788 --- /dev/null +++ b/modules/60-asynchronous-programming/description.es.yml @@ -0,0 +1,8 @@ +--- + +name: Programación asíncrona +description: | + En la programación, a menudo se dan situaciones en las que es necesario retrasar o delegar la ejecución de una instrucción a otra parte del código. + En lugar de esperar a que se complete una tarea, el programa puede continuar realizando otras operaciones mientras supervisa el estado de la tarea asíncrona por separado. + + El asincronismo permite una gestión eficiente del tiempo de ejecución, especialmente al gestionar la latencia, las solicitudes de red y las operaciones de E/S. diff --git a/modules/60-asynchronous-programming/description.ru.yml b/modules/60-asynchronous-programming/description.ru.yml new file mode 100644 index 00000000..3ae4ce60 --- /dev/null +++ b/modules/60-asynchronous-programming/description.ru.yml @@ -0,0 +1,8 @@ +--- + +name: Асинхронное программирование +description: | + В программировании часто возникают ситуации, когда выполнение инструкции нужно отложить или передать другой части кода. + Вместо того чтобы ждать завершения задачи, программа может продолжить выполнение других операций, отслеживая статус асинхронной задачи отдельно. + + Асинхронность позволяет эффективно управлять временем выполнения, особенно при работе с задержками, сетевыми запросами и операциями ввода-вывода.