Есть высоконагруженный веб-сервис, который должен возвращать ветки деревьев, доставаемых из медленной БД. Для упрощения тестовой задачи будем считать, что мы можем прочитать возвращаемые данные из CSV-файлов с именами tree1.csv, tree2.csv, tree3.csv. В этих файлах содержится структура трех разных деревьев. Каждый файл содержит столбцы id, name, parent, где parent – это id родителя элемента.
Запрос на ветвь имеет вид:
{
tree: название файла с деревом,
id: id элемента, с которого строится ветвь
}
Требуется, чтобы сервис порождал заданное количество воркеров wMax для обработки входящих HTTP-запросов, при первом обращении к сервису к какому-либо дереву:
- Проверял, есть ли это дерево в кэше в памяти. Если есть, и дата модификации файла данного дерева не изменилась — отдавал ветку в виде многоуровнего JSON’а:
{
id: ...,
name: ...,
children: [
{
id: ...,
name: ...,
children: null
},
...
]
}
- Если дата модификации дерева изменилась, либо кэша нет, то порождал воркер на создание данного кэша и отдавал ветку, вручную собрав ее из файла (со структурой как в п.1) и не дожидаясь окончания воркера перестройки кэша.
Нужно учесть, что запросов может быть до 100 и более в секунду.
- Есть высоконагруженный проект, один из его REST-интерфейсов принимает на вход структуру вида:
[
{ name: "...", type: "..." },
...
]
Элементов в данной структуре может быть от 1 до 1000. Требуется дополнить каждый элемент этой структуры свойством value, равным порядковому номеру элемента. Как бы вы это сделали?
Использовал бы метод массивов:
array.map((item, idx) => Object.assign(item, {value: idx}))
- Есть массив с идентификаторами элементов вида:
[
id1,
id2,
id3,
…
]
Необходимо для каждого идентификатора получить соответствующую строку таблицы table из БД Postgres (таблица имеет два столбца – id и prop), взять оттуда значение столбца prop и построить структуру вида:
[
id1: prop1,
id2: prop2,
id3: prop3,
...
]
Как бы вы реализовали такую задачу?
Поскольку мы одбираемся по where in (id1….idn), в возвращаемых строках будут фигурировать оба, интересующие нас поля (id, prop)
Думаю, что вы ошиблись со скобками, и мы говорим про объект, а не массив.
Object.fromEntries(rows.map(({id, prop}) => [id, prop]))
- Что предпочтительней использовать – цепочку промисов или async/await? Почему?
Если промисы не зависят друг от друга, я бы использовал Promise.all(). Если промисы должны выполняться последовательно, я бы использовал async/await для повышения читаемости кода.
- Равноценна ли запись f1(...).catch(...) и await f2(...).catch(...), если f1 и f2:
f1 = function(...) {
return new Promise(
( res, rej ) => {
…
}
);
}
async f2(...) {
...
}
Запись не равноценна, так как в первом случае мы не ждем промис, а во втором ждем. Но я думаю, что вы хотели спросить не это. А есть ли разница между функцией объявленной через async и функцией, которая возвращает промис.
Вопрос хитрый, полагаю навеянный данной статьей https://habr.com/ru/post/475260/
Сначала поглядел на статью и написал, что да. Доверяй, но проверяй. Запустил примеры в редакторе и перехватил обе ошибки. Ответ – нет. Либо, я не понял вопрос.
function fn(obj) {
const someProp = obj.someProp
return new Promise((_, reject) => {
reject(someProp)
})
}
async function asyncFn(obj) {
const someProp = obj.someProp
return Promise.reject(someProp)
}
(async ()=>{
const o = {}
await asyncFn(o).catch(err => console.error('Catched')) // => 'Catched'
await fn(o).catch(err => console.error('Catched')) // => 'Catched'
})()
- Как лучше перехватить любую ошибку в цепочке промисов, при async/await? Почему?
Раз мы не обрабатываем их по отдельности, значит в них есть что-то общее и мы можем просто обернуть асинхронные вызовы в try/catch и обработать все в единственном catch.
Так как если мы не обрабатываем ошибку с async то ошибка просто вываливается в текущем контесте.
- Следует ли ставить ; в конце строк JS, если ее можно опустить?
Вообще компилятор сам расставляет их, но можно подорваться на этом если использовать IIFE.
const a = 'ставь точки с запятыми во имя добра'
(() => {
console.log('точечный бог покарает тебя')
})()
В вышеописанном примере будет ошибка.
- Как бы вы реализовали функцию, в которую в качестве параметра передается массив URL. Функция должна получить данные с этих URL и вернуть в виде структуры:
{
url: данные,
…
}
aasync function getData(urls) {
const promises = []
urls.forEach(url => {
promises.push(
// привел пример со сторонней библиотекой, потому что нативные методы не так наглядны
axios.get(url)
.then(r => r)
.catch(e => e)
)
})
const data = await Promise.all(promises)
// В зависимости от http ответов на ошибки, и того как мы хотим их отобразить в результирующем объекте
// можно было бы дописать что-то еще
return Object.fromEntries(
urls.map(
(url, idx) => [url, data[idx].status === 200 ? data[idx] : 'данные не были получены']
)
)
}