Лёгкая библиотека выполнения асинхронной очереди!
Используя npm:
$ npm install async-multiple
import { map } from 'async-multiple'
const задача = [1, 2, 3, 4, 5]
map({
задача,
обработчик: async (элемент) => {
// Вы также можете использовать другие асинхронные функции, такие как fetch или ajax
await this.sleep(1000)
if (элемент === 3) {
return Promise.reject(new Error('Не 3!'))
}
return Promise.resolve(элемент * элемент)
}
})
.then(результат => {
console.log(результат)
})
// Результат
[
{ порядок: 0, вход: 1, выход: 1, ошибка: null },
{ порядок: 1, вход: 2, выход: 4, ошибка: null },
{ порядок: 2,
вход: 3,
выход: null,
ошибка: 'Не 3!', // Объект ошибки
},
{ порядок: 3, вход: 4, выход: 16, ошибка: null },
{ порядок: 4, вход: 5, выход: 25, ошибка: null }
]
import { each } from 'async-multiple'
each({
задача: [
async () => {
return Promise.resolve(1)
},
async () => {
return Promise.resolve(2)
},
async () => {
return Promise.resolve(3)
},
async () => {
return Promise.reject(new Error('Не 4'))
},
async () => {
return Promise.resolve(5)
},
],
})
.then(результат => {
console.log(результат.toArray())
})
// Результат
[
{ порядок: 0, выход: 1, ошибка: null },
{ порядок: 1, выход: 2, ошибка: null },
{ порядок: 2, выход: 3, ошибка: null },
{ порядок: 3,
выход: null,
ошибка: 'Не 4'
},
{ порядок: 5, выход: 5, ошибка: null }
]
Цикл задач можно создать путём передачи соответствующего конфига в map
.
map({
задача: [1, 2, 3, 4, 5]
})
map({
задача: ['файл1', 'файл2', 'файл3', 'файл4', 'файл5']
})
Когда обработчик не возвращает промис, но вместо этого возвращает значение, такое как число или строку, это значение будет обёрнуто в Promise.resolve
.
Если нет возврата, задача останавливается на этом шаге!
// Возвращает значение
map({
задача: [1, 2, 3, 4, 5],
обработчик: вход => вход
})
// То же самое что
map({
задача: [1, 2, 3, 4, 5],
обработчик: вход => Promise.resolve(вход)
})
// Обработка ошибки
map({
задача: [1, 2, 3, 4, 5],
обработчик: вход => {
if (вход === 3) {
return Promise.reject(new Error('Не 3, завершено с ошибкой!'))
}
return Promise.resolve(вход)
}
})
// Использование async/await
map({
задача: [1, 2, 3, 4, 5],
обработчик: async вход => {
await sleep(1000)
return Promise.resolve(вход)
}
})
map({ task: [1, 2, 3, 4, 5], handle: input => { if (input === 3) { return Promise.reject(new Error('not 3!')) } return Promise.resolve(input) }, rejectOnError: true }) // результат [ { порядок: 0, вход: 1, выход: 1, ошибка: null }, { порядок: 1, вход: 2, выход: 4, ошибка: null }, { порядок: 2, вход: 3, выход: null, ошибка: 'not 3!', // object error } ]
Корректировка:
```js
map({
task: [1, 2, 3, 4, 5],
handle: input => {
if (input === 3) {
return Promise.reject(new Error('not 3!'))
}
return Promise.resolve(input)
},
rejectOnError: true
})
// результат
[
{ порядок: 0, вход: 1, выход: 1, ошибка: null },
{ порядок: 1, вход: 2, выход: 4, ошибка: null },
{ порядок: 2,
вход: 3,
выход: null,
ошибка: 'не 3!', // объект ошибки
}
]
```#### случайный_шаг
##### обязательный: нет тип: boolean значение по умолчанию: false
##### установка значения true: случайный вызов задачи
##### пример
```js
map({
task: [1, 2, 3, 4, 5],
handle: async (элемент) => {
return Promise.resolve(элемент)
},
случайный_шаг: true,
handleStart: ({ шаг, вход }) => {
console.log(`начало обработки на шаге ${шаг}, вход: ${вход}`)
},
})
.then(результат => {
console.log(результат.toArray())
})
// результат
начало обработки на шаге 0, вход: 2
начало обработки на шаге 1, вход: 5
начало обработки на шаге 2, вход: 1
начало обработки на шаге 3, вход: 3
начало обработки на шаге 4, вход: 4
[
{ порядок: 0, вход: 1, выход: 1, ошибка: null },
{ порядок: 1, вход: 2, выход: 2, ошибка: null },
{ порядок: 2, вход: 3, выход: 3, ошибка: null },
{ порядок: 3, вход: 4, выход: 4, ошибка: null },
{ порядок: 4, вход: 5, выход: 5, ошибка: null }
]
// каждая задача будет ждать 1000 миллисекунд перед выполнением
map({
task: [1, 2, 3, 4, 5],
handle: async (элемент) => {
return Promise.resolve(элемент)
},
шаг_между: 1000
})
// каждая задача будет ждать 500~2000 миллисекунд перед выполнением
map({
task: [1, 2, 3, 4, 5],
handle: async (элемент) => {
return Promise.resolve(элемент)
},
шаг_между: [500, 2000]
})
// Если время выполнения шага больше stepTimeout, этот шаг будет отклонён, затем вызовется следующий шаг, // и получен будет ошибочный ответ с таймаутом. map({ task: [1, 2, 3, 4, 5], handle: someFunction, // асинхронная функция, например fetch или readFile stepTimeout: 1000 })
##### Обязательный: Нет Тип: Число Значение по умолчанию: 0
##### Пример
```js
// Если установлено, при получении отказа, обработчик будет повторно вызван в следующем шаге
// Если количество вызовов превышает errorRetry, будет получен ошибочный результат, затем вызван следующий шаг
const task = [1, 2, 3, 4, 5];
let flag = false;
map({
task,
handle: async (item) => {
if (item === 3) {
if (flag === false) {
flag = true;
return Promise.reject(new Error('Флаг равен false'));
}
return Promise.resolve(item);
}
return Promise.resolve(item);
},
errorRetry: 3,
handleStart: ({ step, input, isRetry }) => {
console.log(`Начало обработки на шаге ${step}, входные данные: ${input} ${isRetry ? '[Повтор]' : ''}`);
},
});
.then(result => {
console.log(result.toArray());
});
// Если установлено, при получении достаточного количества успешных результатов, задача будет завершена
map({
task: [1, 2, 3, 4, 5],
handle: someFunction, // Асинхронная функция, например fetch или readFile
maxSuccessCount: 3
});
// Результат
начало обработки на шаге 0, входные данные: 1
начало обработки на шаге 1, входные данные: 2
начало обработки на шаге 2, входные данные: 3
[async-multiple MESSAGE]: Достаточно успешных результатов, задача завершена!
[
{ порядок: 0, входные данные: 1, выходные данные: 1, ошибка: null },
{ порядок: 1, входные данные: 2, выходные данные: 2, ошибка: null },
{ порядок: 2, входные данные: 3, выходные данные: 3, ошибка: null }
]
```#### showProgress
##### Обязательный: Нет Тип: Логический Значение по умолчанию: False
##### Пример
```js
// Если установлено, при получении достаточного количества успешных результатов, задача будет завершена
const task = [1, 2, 3, 4, 5];
map({
task,
handle: async (item) => {
return Promise.resolve(item);
},
showProgress: true
});
then(result => {
console.log(result.toArray());
});
// result [TASK_csv1LTmw] Все: 5 Завершено: 1 Прогресс: 20.00% [TASK_csv1LTmw] Все: 5 Завершено: 2 Прогресс: 40.00% [TASK_csv1LTmw] Все: 5 Завершено: 3 Прогресс: 60.00% [TASK_csv1LTmw] Все: 5 Завершено: 4 Прогресс: 80.00% [TASK_csv1LTmw] Все: 5 Завершено: 5 Прогресс: 100.00% [ { order: 0, input: 1, output: 1, error: null }, { order: 1, input: 2, output: 2, error: null }, { order: 2, input: 3, output: 3, error: null }, { order: 3, input: 4, output: 4, error: null }, { order: 4, input: 5, output: 5, error: null } ]
##### Обязательный: Нет Тип: Строка Значение по умолчанию: Неопределено
##### Пример
```js
// Если установлено, задача будет отменена при получении достаточного количества решений и остановлена на следующем шаге
const task = [1, 2, 3, 4, 5];
map({
task,
handle: async (item) => {
return Promise.resolve(item);
},
showProgress: true,
alias: 'loop task'
});
then(result => {
console.log(result.toArray());
});// результат
[ loop task ] всего: 5 завершено: 1 прогресс: 20.00%
[ loop task ] всего: 5 завершено: 2 прогресс: 40.00%
[ loop task ] всего: 5 завершено: 3 прогресс: 60.00%
[ loop task ] всего: 5 завершено: 4 прогресс: 80.00%
[ loop task ] всего: 5 завершено: 5 прогресс: 100.00%
[
{ порядок: 0, входной_данные: 1, выходной_данные: 1, ошибка: null },
{ порядок: 1, входной_данные: 2, выходной_данные: 2, ошибка: null },
{ порядок: 2, входной_данные: 3, выходной_данные: 3, ошибка: null },
{ порядок: 3, входной_данные: 4, выходной_данные: 4, ошибка: null },
{ порядок: 4, входной_данные: 5, выходной_данные: 5, ошибка: null }
]
```#### handleStart | handleEnd
##### Обязательный: Нет Тип: Функция Значение по умолчанию: Неопределено
##### Пример
```js
const task = [1, 2, 3, 4, 5];
map({
task,
handle: async (item) => {
return Promise.resolve(item);
},
handleStart: ({ step, input, isRetry }) => {
console.log(`начало обработки на шаге ${step}, входные данные: ${input} ${isRetry ? '[повторение]' : ''}`);
},
handleEnd: ({ step, input, isRetry }) => {
console.log(`конец обработки на шаге ${step}, входные данные: ${input} ${isRetry ? '[повторение]' : ''}`);
},
});
.then((result) => {
console.log(result.toArray());
});
// Результат
начало обработки на шаге 0, входные данные: 1
конец обработки на шаге 0, входные данные: 1
начало обработки на шаге 1, входные данные: 2
конец обработки на шаге 1, входные данные: 2
начало обработки на шаге 2, входные данные: 3
конец обработки на шаге 2, входные данные: 3
начало обработки на шаге 3, входные данные: 4
конец обработки на шаге 3, входные данные: 4
начало обработки на шаге 4, входные данные: 5
конец обработки на шаге 4, входные данные: 5
[
{ порядок: 0, входной_данный: 1, выходной_данный: 1, ошибка: null },
{ порядок: 1, входной_данный: 2, выходной_данный: 2, ошибка: null },
{ порядок: 2, входной_данный: 3, выходной_данный: 3, ошибка: null },
{ порядок: 3, входной_данный: 4, выходной_данный: 4, ошибка: null },
{ порядок: 4, входной_данный: 5, выходной_данный: 5, ошибка: null }
]
Все параметры такие же как в map
, за исключением task
и handle
(каждый не имеет этих параметров).#### задача
const задача = [
() => {}, // что делать 1
() => {}, // что делать 2
() => {}, // что делать 3
() => {}, // что делать 4
]
map({
задача,
})
.then(результат => {
console.log(результат.toArray())
})
import { Map, Each } from 'async-multiple'
const цикл = new Map({
задача: [1, 2, 3, 4, 5],
обработчик: s => s,
})
цикл.start().then(
результат => {
console.log(результат)
}
)
const цикл = new Each({
задача: [
() => {}, // что делать 1
() => {}, // что делать 2
() => {}, // что делать 3
() => {}, // что делать 4
],
})
цикл.start().then(
результат => {
console.log(результат)
}
)
вызовите этот метод для запуска задачи, возвращает промис
вызовите этот метод для отмены задачи глобально
import { Event } from 'async-multiple'
const eventBus = new Event({ debug: true })
eventBus.on('action1', (params) => {
console.log('action1 called!', params)
}, 5)
eventBus.on('action1', (params) => {
console.log('action1 called!', params)
}, 5)
setInterval(() => {
eventBus.emit('action1', '123')
}, 1000)
actionName: название действия, которое вы прослушиваете callback: обратный вызов, параметры — полученные данные callTime: максимальное количество вызовов обратного вызова, если не указано, ограничение отсутствует
Вы можете зарегистрировать его несколько раз, как показано ниже:```js import { Event } from 'async-multiple'; const eventBus = new Event({ debug: true });
eventBus.on('action1', (params) => { console.log('action1 called! function 1', params); });
eventBus.on('action1', (params) => { console.log('action1 called! function 2', params); });
setInterval(() => { eventBus.emit('action1', '123'); }, 1000);
Каждый обратный вызов будет выполнен
##### one-time
###### параметры
actionName: действие, которое вы прослушиваете
callback: обратный вызов, параметры — полученные данные, может быть вызван один раз
##### emit
###### параметры
actionName: действие, которое вы отправляете
data: данные, которые вы отправляете
## TODO
#### одновременный запуск нескольких задач
## Лицензия (MIT)
Авторское право © 2019 Leo Согласно настоящей лицензии бесплатно предоставляется каждому лицу, получившему копию данного программного обеспечения и связанных с ним документов («Программное обеспечение»), право использовать Программное обеспечение без каких-либо ограничений, включая, но не ограничиваясь правами на использование, копирование, изменение, объединение, публикацию, распространение, предоставление sublicense (подлицензии) и/или продажу копий Программного обеспечения, а также право допускать других лиц к использованию Программного обеспечения при условии соблюдения следующих условий:
Приведённое выше уведомление об авторском праве и это уведомление о разрешении должны присутствовать во всех копиях или значительных частях Программы.
```ПРОГРАММА предоставляется «КАК ЕСТЬ», БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ, ЯВНО ВЫДАВаемых ИЛИ
НЕЯВНО ВЫДАВаемых, ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИВАЯСЬ ГАРАНТИЯМИ ТОРГОВЛЕНИЯ, ПРИГОДНОСТИ ДЛЯ
ОСОБОЙ ЦЕЛИ И НЕНАРУШЕНИЯ ПРАВ. В НИКАКОМ СЛУЧАЕ АВТОРЫ ИЛИ
владельцы авторских прав НЕ БУДУТ ОТВЕТСТВЕННЫМИ ЗА ЛЮБЫЕ ПРЕТЕНДИРОВАННЫЕ УЩЕРБЫ, УЩЕРБЫ ИЛИ
ДРУГИЕ ОТВЕТСТВЕННОСТИ, НАПРАВЛЕННЫЕ НА ДЕЙСТВИЕ КОНТРАКТА, ДЕЛИКТ ИЛИ ДРУГОЕ,
ВОЗНИКАЮЩИЕ ИЗ, ЧЕРЕЗ ИЛИ В СВЯЗИ С ПРОГРАМОЙ ИЛИ ИСПОЛЬЗОВАНИЕМ ИЛИ ДРУГИМИ
ДЕЙСТВИЯМИ С ПРОГРАММНЫМ ОБЕСПЕЧЕНИЕМ.
---
Перевод:
**ПРОГРАММА предоставляется «КАК ЕСТЬ», БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ, ЯВНО ВЫДАВаемых ИЛИ
НЕЯВНО ВЫДАВаемых, ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИВАЯСЬ ГАРАНТИЯМИ ТОРГОВЛЕНИЯ, ПРИГОДНОСТИ ДЛЯ
ОСОБОЙ ЦЕЛИ И НЕНАРУШЕНИЯ ПРАВ. В НИКАКОМ СЛУЧАЕ АВТОРЫ ИЛИ
владельцы авторских прав НЕ БУДУТ ОТВЕТСТВЕННЫМИ ЗА ЛЮБЫЕ ПРЕТЕНДИРОВАННЫЕ УЩЕРБЫ, УЩЕРБЫ ИЛИ
ДРУГИЕ ОТВЕТСТВЕННОСТИ, НАПРАВЛЕННЫЕ НА ДЕЙСТВИЕ КОНТРАКТА, ДЕЛИКТ ИЛИ ДРУГОЕ,
ВОЗНИКАЮЩИЕ ИЗ, ЧЕРЕЗ ИЛИ В СВЯЗИ С ПРОГРАМОЙ ИЛИ ИСПОЛЬЗОВАНИЕМ ИЛИ ДРУГИМИ
ДЕЙСТВИЯМИ С ПРОГРАММНЫМ ОБЕСПЕЧЕНИЕМ.**
---
Исправленный вариант:
**ПРОГРАММА предоставляется «КАК ЕСТЬ», БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ, ЯВНО ВЫДАВаемых ИЛИ НЕЯВНО ВЫДАВаемых, ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИВАЯСЬ ГАРАНТИЯМИ ТОРГОВЛЕНИЯ, ПРИГОДНОСТИ ДЛЯ ОСОБОЙ ЦЕЛИ И НЕНАРУШЕНИЯ ПРАВ. В НИКАКОМ СЛУЧАЕ АВТОРЫ ИЛИ владельцы авторских прав НЕ БУДУТ ОТВЕТСТВЕННЫМИ ЗА ЛЮБЫЕ ПРЕТЕНДИРОВАННЫЕ УЩЕРБЫ, УЩЕРБЫ ИЛИ ДРУГИЕ ОТВЕТСТВЕННОСТИ, НАПРАВЛЕННЫЕ НА ДЕЙСТВИЕ КОНТРАКТА, ДЕЛИКТ ИЛИ ДРУГОЕ, ВОЗНИКАЮЩИЕ ИЗ, ЧЕРЕЗ ИЛИ В СВЯЗИ С ПРОГРАМОЙ ИЛИ ИСПОЛЬЗОВАНИЕМ ИЛИ ДРУГИМИ ДЕЙСТВИЯМИ С ПРОГРАММНЫМ ОБЕСПЕЧЕНИЕМ.**
---
Финальный текст:
**ПРОГРАММА предоставляется «КАК ЕСТЬ», БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ, ЯВНО ВЫДАВаемых ИЛИ НЕЯВНО ВЫДАВаемых, ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИВАЯСЬ ГАРАНТИЯМИ ТОРГОВЛЕНИЯ, ПРИГОДНОСТИ ДЛЯ ОСОБОЙ ЦЕЛИ И НЕНАРУШЕНИЯ ПРАВ. В НИКАКОМ СЛУЧАЕ АВТОРЫ ИЛИ владельцы авторских прав НЕ БУДУТ ОТВЕТСТВЕННЫМИ ЗА ЛЮБЫЕ ПРЕТЕНДИРОВАННЫЕ УЩЕРБЫ, УЩЕРБЫ ИЛИ ДРУГИЕ ОТВЕТСТВЕННОСТИ, НАПРАВЛЕННЫЕ НА ДЕЙСТВИЕ КОНТРАКТА, ДЕЛИКТ ИЛИ ДРУГОЕ, ВОЗНИКАЮЩИЕ ИЗ, ЧЕРЕЗ ИЛИ В СВЯЗИ С ПРОГРАМОЙ ИЛИ ИСПОЛЬЗОВАНИЕМ ИЛИ ДРУГИМИ ДЕЙСТВИЯМИ С ПРОГРАММНЫМ ОБЕСПЕЧЕНИЕМ.**
---
Итоговый текст:
**ПРОГРАММА предоставляется «КАК ЕСТЬ», БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ, ЯВНО ВЫДАВаемых ИЛИ НЕЯВНО ВЫДАВаемых, ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИВАЯСЬ ГАРАНТИЯМИ ТОРГОВЛЕНИЯ, ПРИГОДНОСТИ ДЛЯ ОСОБОЙ ЦЕЛИ И НЕНАРУШЕНИЯ ПРАВ. В НИКАКОМ СЛУЧАЕ АВТОРЫ ИЛИ владельцы авторских прав НЕ БУДУТ ОТВЕТСТВЕННЫМИ ЗА ЛЮБЫЕ ПРЕТЕНДИРОВАННЫЕ УЩЕРБЫ, УЩЕРБЫ ИЛИ ДРУГИЕ ОТВЕТСТВЕННОСТИ, НАПРАВЛЕННЫЕ НА ДЕЙСТВИЕ КОНТРАКТА, ДЕЛИКТ ИЛИ ДРУГОЕ, ВОЗНИКАЮЩИЕ ИЗ, ЧЕРЕЗ ИЛИ В СВЯЗИ С ПРОГРАМОЙ ИЛИ ИСПОЛЬЗОВАНИЕМ ИЛИ ДРУГИМИ ДЕЙСТВИЯМИ С ПРОГРАММНЫМ ОБЕСПЕЧЕНИЕМ.**
---
Итоговый текст:
**ПРОГРАММА предоставляется «КАК ЕСТЬ», БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ, ЯВНО ВЫДАВаемых ИЛИ НЕЯВНО ВЫДАВаемых, ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИВАЯСЬ ГАРАНТИЯМИ ТОРГОВЛЕНИЯ, ПРИГОДНОСТИ ДЛЯ ОСОБОЙ ЦЕЛИ И НЕНАРУШЕНИЯ ПРАВ. В НИКАКОМ СЛУЧАЕ АВТОРЫ ИЛИ владельцы авторских прав НЕ БУДУТ ОТВЕТСТВЕННЫМИ ЗА ЛЮБЫЕ ПРЕТЕНДИРОВАННЫЕ УЩЕРБЫ, УЩЕРБЫ ИЛИ ДРУГИЕ ОТВЕТСТВЕННОСТИ, НАПРАВЛЕННЫЕ НА ДЕЙСТВИЕ КОНТРАКТА, ДЕЛИКТ ИЛИ ДРУГОЕ, ВОЗНИКАЮЩИЕ ИЗ, ЧЕРЕЗ ИЛИ В СВЯЗИ С ПРОГРАМОЙ ИЛИ ИСПОЛЬЗОВАНИЕМ ИЛИ ДРУГИМИ ДЕЙСТВИЯМИ С ПРОГРАММНЫМ ОБЕСПЕЧЕНИЕМ.**
---
Итоговый текст:
**ПРОГРАММА предоставляется «КАК ЕСТЬ», БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ, ЯВНО ВЫДАВаемых ИЛИ НЕЯВНО ВЫДАВаемых, ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИВАЯСЬ ГАРАНТИЯМИ ТОРГОВЛЕНИЯ, ПРИГОДНОСТИ ДЛЯ ОСОБОЙ ЦЕЛИ И НЕНАРУШЕНИЯ ПРАВ. В НИКАКОМ СЛУЧАЕ АВТОРЫ ИЛИ владельцы авторских прав НЕ БУДУТ ОТВЕТСТВЕННЫМИ ЗА ЛЮБЫЕ ПРЕТЕНДИРОВАННЫЕ УЩЕРБЫ, УЩЕРБЫ ИЛИ ДРУГИЕ ОТВЕТСТВЕННОСТИ, НАПРАВЛЕННЫЕ НА ДЕЙСТВИЕ КОНТРАКТА, ДЕЛИКТ ИЛИ ДРУГОЕ, ВОЗНИКАЮЩИЕ ИЗ, ЧЕРЕЗ ИЛИ В СВЯЗИ С ПРОГРАМОЙ ИЛИ ИСПОЛЬЗОВАНИЕМ ИЛИ ДРУГИМИ ДЕЙСТВИЯМИ С ПРОГРАММНЫМ ОБЕСПЕЧЕНИЕМ.**
---
Итоговый текст:
**ПРОГРАММА предоставляется «КАК ЕСТЬ», БЕЗ КАКИХ-ЛИ
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Комментарии ( 0 )