ЦИТК-795: CodeReview - deepMerge в стрелочном стиле, дополнительные комментарии по коду
This commit is contained in:
parent
72feca2a38
commit
b2b7d01342
@ -30,8 +30,9 @@ const { SPROTOCOL_HTTP, SPROTOCOL_KAFKA } = require("../models/obj_service"); //
|
||||
|
||||
//Глубокое клонирование
|
||||
const deepClone = value => {
|
||||
//Клонируем объект в зависимости от его типа, сохраняя прототипы
|
||||
//Буфер для фиксации "клонированных" элементов исходного объекта
|
||||
const seen = new WeakMap();
|
||||
//Функция рекурсивного клонирования (разбирает тип полученного значения и в зависимости от него выполняет клонирование, сохраняя прототипы)
|
||||
const clone = val => {
|
||||
//Примитивы и функции возвращаем как есть
|
||||
if (val === null || typeof val !== "object") return val;
|
||||
@ -104,10 +105,12 @@ const deepClone = value => {
|
||||
});
|
||||
return obj;
|
||||
};
|
||||
//Выполняем копирование рекурсивно с верхнего уровня
|
||||
try {
|
||||
//Возвращаем что получилось
|
||||
return clone(value);
|
||||
} catch (e) {
|
||||
//В случае непредвиденной ошибки формируем информативное исключение
|
||||
//В случае непредвиденной ошибки формируем исключение
|
||||
const err = new Error("Ошибка глубокого копирования объекта");
|
||||
err.originalError = e;
|
||||
throw err;
|
||||
@ -407,30 +410,33 @@ const getNowString = () => {
|
||||
};
|
||||
|
||||
//Глубокое слияние объектов
|
||||
function deepMerge(...sources) {
|
||||
const deepMerge = (...sources) => {
|
||||
//Проверка на простой объект (не имеет специального поведения или прототипа)
|
||||
const isPlainObject = value => Object.prototype.toString.call(value) === "[object Object]";
|
||||
|
||||
const cloneValue = value => {
|
||||
return deepClone(value);
|
||||
};
|
||||
|
||||
//Клоникарование значения
|
||||
const cloneValue = value => deepClone(value);
|
||||
//Буфер для результата
|
||||
const target = {};
|
||||
|
||||
//Обходим входные параметры по очереди
|
||||
for (const source of sources) {
|
||||
//Пропускаем непростые объекты - сливать можем только простые
|
||||
if (!isPlainObject(source)) continue;
|
||||
|
||||
//Обходим пары "ключ-значение"
|
||||
for (const [key, value] of Object.entries(source)) {
|
||||
//Если значение ключа - объект
|
||||
if (isPlainObject(value)) {
|
||||
//Сливаем рекурсивно
|
||||
if (!isPlainObject(target[key])) target[key] = {};
|
||||
target[key] = deepMerge(target[key], value);
|
||||
} else {
|
||||
//Примитивы - просто клонируем
|
||||
target[key] = cloneValue(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Возвращаем собранный буфер, содержащий все слитые воедино объекты-параметры
|
||||
return target;
|
||||
}
|
||||
};
|
||||
|
||||
//Глубокое копирование объекта
|
||||
const deepCopyObject = obj => JSON.parse(JSON.stringify(obj));
|
||||
@ -509,27 +515,31 @@ const getURLProtocol = sURL => {
|
||||
|
||||
//Обёртывание промиса в таймаут исполнения
|
||||
const wrapPromiseTimeout = (timeout, executor) => {
|
||||
//Проверяем входные параметры - должен быть указан ненулевой таймаут и функция-исполнитель промиса
|
||||
if (!timeout || typeof executor !== "function") {
|
||||
//Разрешаем сразу, не ожидая
|
||||
return executor ? executor() : Promise.resolve();
|
||||
}
|
||||
|
||||
//Параметры прошли проверку, создаем экхемпляр контроллера прерывания асинхронного процесса
|
||||
const controller = new AbortController();
|
||||
//Подготовим объект для выбрасывания ошибки
|
||||
const sMessage = `Истёк интервал ожидания (${timeout} мс) завершения асинхронного процесса.`;
|
||||
const timeoutError = new Error(sMessage);
|
||||
timeoutError.error = sMessage;
|
||||
|
||||
//Буфер для идентификатора таймера
|
||||
let timeoutPid;
|
||||
|
||||
//Создаём промис с взведенным таумером на у казанный таймаут, промис будет "отклонён" по истечении таймера, но перед этим контроллер прерывания выдаст "сигнал" на отмену осинхронного процесса
|
||||
const timeoutPromise = new Promise((_, reject) => {
|
||||
timeoutPid = setTimeout(() => {
|
||||
controller.abort(timeoutError);
|
||||
reject(timeoutError);
|
||||
}, timeout);
|
||||
});
|
||||
|
||||
//Создаём промис с функцией-исполнителем асинхронного процесса
|
||||
const taskPromise = Promise.resolve(executor(controller.signal));
|
||||
|
||||
//Запускаем оба промиса в режиме "гонка" - кто "быстрее" исполнится
|
||||
return Promise.race([taskPromise, timeoutPromise]).finally(() => {
|
||||
//В любом случае не забываем зачистить взведённый таймер
|
||||
if (timeoutPid) clearTimeout(timeoutPid);
|
||||
});
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user