Comments 20
Lazy-load штука хорошая. Но я бы вам рекомендовал посмотреть на асинхронные задачи, все-таки в самой ноде обычно проводится на порядок меньше времени, чем в libuv.
К тому же клиент обычно не сразу инициализируется, а времени на загрузку тратится совсем немного.
У меня сейчас примерно так работает одна система, которая весьма бодро аггрегирует данные из соцсетей.
К тому же клиент обычно не сразу инициализируется, а времени на загрузку тратится совсем немного.
У меня сейчас примерно так работает одна система, которая весьма бодро аггрегирует данные из соцсетей.
//noinspection JSUnresolvedVariable
var remaining_thread_count = Number(process.env.THREAD_COUNT) || 150;
export async function init() {
...миграции БД...
while (remaining_thread_count--)
/*important! not an async call, that's an fibering*/
start_thread();
}
async function start_thread() {
await (await getNextTask());
start_thread();
}
0
await (await getNextTask());
оО
await ожидает промис, а промис не может зарезолвить промис, таким образом что делает этот код?
0
Интересно. Не является ли это специфичной для async/await «фичей», или багом regenerator?
function test() {
return new Promise((resolve) => {
resolve(Promise.resolve(5));
});
}
test().then((val) => console.log(val)) // 5
0
таки нет, вы не правы.
Этот код вполне рабочий:
И да, все async-функции возвращают промис, как результат работы, by design.
Этот код вполне рабочий:
(async function start_thread() {
const result = await getNextTask();
console.log(`got ${result} from promise`);
})();
async function getNextTask(){
return new Promise(resolve => resolve(5))
}
// этот код эквивалентен
log(await (await foo()));
// этому
foo().then(r => r).then(r => log(r));
И да, все async-функции возвращают промис, как результат работы, by design.
0
По началу, я тоже использовал одновременное асинхронное выполнение кода в несколько потоков. Но, код выполняется в одном процессе, соответственно, на одном ядре CPU. Для использования максимума ресурсов обычно используется оба подхода: код работает в несколько процессов, каждый процесс из которых выполняет код в несколько потоков.
Повышать количество потоков в каждом процессе может быть выгодно для экономии оперативной памяти, т.к. модули для второго и последующих потоков уже загруженны. Главное — не переборщить, во избежание зависания процессов. Но использование нескольких процессов тоже неизбежно.
Повышать количество потоков в каждом процессе может быть выгодно для экономии оперативной памяти, т.к. модули для второго и последующих потоков уже загруженны. Главное — не переборщить, во избежание зависания процессов. Но использование нескольких процессов тоже неизбежно.
0
Кроме того, процессы node могут иметь такие состояния, когда их необходимо завершить или перезапустить:
- idle: процесс использует CPU на 0% продолжительное время. Тут может быть два варианта: если процесс выполнял какую-то работу, скорее всего процесс по какой-то причине потерял callback или что-то в этом роде. Такой процесс необходимо перезагрузить. Если данный процесс реализует, например, http-сервер с каким-нибудь малопосещаемым сайтом, то скорее всего такое состояние обусловленно тем, что на сайт никто давно не заходил. Такой процесс можно завершить, а при запросе на сайт, снова по быстрому поднять http-сервер.
- CPU-limit: процесс использует CPU на 100% (или свой ограниченный максимум) продолжительное время. Такой процесс скорее всего зациклился или попал на невыполнимый участок задачи. Такой процесс можно перезагрузить, чтобы сам не застревал на одной задаче и не мешал другим конкурирующим процессам.
- RAM-limit: процесс использует максимум выделенной для него памяти. Не секрет, что node-процессы по ходу своего выполнения текут. Совсем ожиревшие процессы тоже можно перезагружать. Это напоминает борьбу с утечками методом PHP. — То есть, зачем удалять ненужные переменные?! — все переменные удаляются вместе с завершением процесса.
0
Без
Реализация модуля storage:
Вместо этого:
Загрузка модуля с провайдером выглядит так:
Object.defineProperty
эта задача прекрасно решалась, просто библиотека вместо хеша конструкторов должна возвращать функцию с одним параметром — именем провайдера. Это можно назвать фабрикой конструкторов. Фабрика делает нужный require
и выглядит это гораздо лаконичнее.Реализация модуля storage:
module.exports = function(providerName) {
return require('./'+providerName+'-storage.jsx');
};
Вместо этого:
var storage = require('storage');
var fsStorage = new storage.FsStorage();
Загрузка модуля с провайдером выглядит так:
var storageConstructor = require('storage')('fs'),
fsStorage = new storageConstructor();
+2
Вы правы, можно обойтись и без
Правда, я не использую в проектах фабрики из-за ненаглядности структуры кода, например, для IDE.
Так же мы используем общую документацию по всем проектам, пакетам, модулям. Для представления списка всех классов в древовидной форме, нам приходится лишь помогать jsdoc лишь указывая что есть
Object.defineProperty()
.Правда, я не использую в проектах фабрики из-за ненаглядности структуры кода, например, для IDE.
Так же мы используем общую документацию по всем проектам, пакетам, модулям. Для представления списка всех классов в древовидной форме, нам приходится лишь помогать jsdoc лишь указывая что есть
@constructor
, а что @namespace
. Использование фабрик требовало бы модернизации сборщика/генератора документации.0
А что, jsdoc хорошо понимает добавление геттеров через
Object.defineProperty
?0
Нет, как раз за это отвечает метки
Например, для обозначения namespace я добавлю в
А для класса, например:
Классы я обычно определяю олдскул-способом
Так, jsdoc шарится по всем файлам исходных кодов, а IDE тоже прекрасно понимает такие комментарии, структура кода всегда под рукой. Код готов к любому рефакторингу.
@constructor
, @namespace
и остальные.Например, для обозначения namespace я добавлю в
index.js
:/** @namespace storage */
А для класса, например:
/**
* @name storage.FsStorage
* @extends storage.BaseStorage
* @constructor
*/
Классы я обычно определяю олдскул-способом
Function().prototype
. Так, jsdoc шарится по всем файлам исходных кодов, а IDE тоже прекрасно понимает такие комментарии, структура кода всегда под рукой. Код готов к любому рефакторингу.
0
Вообще, меня jsdoc и IDE (все) очень огорчают. JavaScript не мыслим без примесей, замыканий и фабрик, а я вообще не могу жить без динамических примесей в прототипы. Они позволяют мне писать в 10 раз меньше кода. Пока не удалось найти систему комментирования исходников, генерации доков, или даже систему автодополнения кода для IDE, которая бы все это могла адекватно отпарсить и уразуметь. Ее конечно можно написать, но что-то подсказывает мне, что она будет очень. Обратное решение, когда все нужно декларировать явно, потребует много писанины в комментариях. Так что, единственный приличный способ сделать это, по моему мнению, это чтобы IDE подключались через дебагер к процессам и показывали содержимое прямо из памяти.
0
Я не понимаю вашего негодования.
Я не против фабрик, но у каждого класса должно быть «жесткое» имя, закрепленное в своем namespace.
То есть, да, разумно к тому коду, что есть приделать возможность получения класса через фабрику. Это бы помогло в случае, например, если тип хранилища указан в конфиге. Но обязательно должна остаться возможность получить класс и по «жесткой» ссылке.
Замыкания к процессу документирования вообще никакой гранью не могу отнести.
По поводу динамических примесей в прототипы. На Node.JS это реализованно
А в jsdoc множественное наследование можно описать:
Я не против фабрик, но у каждого класса должно быть «жесткое» имя, закрепленное в своем namespace.
То есть, да, разумно к тому коду, что есть приделать возможность получения класса через фабрику. Это бы помогло в случае, например, если тип хранилища указан в конфиге. Но обязательно должна остаться возможность получить класс и по «жесткой» ссылке.
/**
* @name storage.getStorage
* @returns {storage.FsStorage|storage.MysqlStorage|storage.MongoStorage}
*/
Замыкания к процессу документирования вообще никакой гранью не могу отнести.
По поводу динамических примесей в прототипы. На Node.JS это реализованно
util.inherits()
. А в jsdoc множественное наследование можно описать:
/**
* @name storage.MysqlStorage
* @extends {storage.BaseStorage|storage.SqlStorage}
* @constructor
*/
0
Где негодование? Нет признаков негодования.
Зачем нужна возможность именования классов по жесткой ссылке?
Замыкания относятся к документированию потому, что это не только способ написания прикладного кода, а еще и способ непрямого наследования. При использовании замыканий наследуются и переопределяются не классы и прототипы, а функции. Например каррирование — это функциональное наследование через замыкания. Например:
Можем теперь делать: или сразу
Теперь про
Зачем нужна возможность именования классов по жесткой ссылке?
Замыкания относятся к документированию потому, что это не только способ написания прикладного кода, а еще и способ непрямого наследования. При использовании замыканий наследуются и переопределяются не классы и прототипы, а функции. Например каррирование — это функциональное наследование через замыкания. Например:
function curry(x) {
return function(y) {
return x + y;
}
}
Можем теперь делать: или сразу
var res = curry(4)(5);
или получать унаследованную функцию var fn = curry(4);
и потом var var res = fn(5);
С первого взгляда, может быть непонятно, зачем наследовать функции, но таким способом можно реализовывать метапрограммирование (порождающее программирование), см. примеры: habrahabr.ru/post/227753 Там замыкания повсеместно для порождения модификаций используются, и как это скормить в jsdoc? Это же все в рантайме создается.Теперь про
util.inherits();
Это способ классового наследования. Это не имеет ни какого отношения к примесям в прототипы. Примеси в прототипы нужны когда мы хотим, опять же, динамически создать прототип для массового порождения объектов. Например, имеем Client.prototype
, и заранее мы не знаем, будет включен или отключен модуль безопасности. Когда он включен, то делается require('security')(Client);
И уже сам модуль безопасности примешивает к Client.prototype
свои методы, например: Client.prototype.signIn(login, password);
и перекрывает своими методами часть базовых, Client
же не знал до этого что есть методы модуля безопасности, и он должен так расширить Client
, чтобы новые методы объявить и вызывать их из уже имеющихся.0
По части
По поводу примисей и наследования я понял, что Вы хотели донести. Но все это можно реализовать и с
То есть, например, есть классы Security и Client. Если реализовать так, то методы и свойства Security будут поверх Client:
Как оформить сие добро в jsdoc не могу уверенно предложить. Но, могу с уверенностью сказать, может примиси и удобный для web инструмент (в браузере много стандартных классов, в которых можно расширять функционал: HTMLDocument, XMLHttpRequest), но в Node.JS я бы уверенно обходился бы без них, с базовым одноуровневым наследованием.
Так или иначе, все зависит от конкретной задачи.
curr
вы правы. Для корректного понимания IDE можно добавить в комментарий @returns {function}
. Ну, а как пользоваться сей конструкцией можно разъяснить в свободной форме в формате markdown в том же комментарии.По поводу примисей и наследования я понял, что Вы хотели донести. Но все это можно реализовать и с
util.inherits()
. Разница лишь в том, что util.inherits(Client, Security)
оставит методы и свойства Client, если таковые имеются в Security.То есть, например, есть классы Security и Client. Если реализовать так, то методы и свойства Security будут поверх Client:
var SecurityClient = mixClass(Client, Security);
function mixClass(cl, mx) {
var resClass = function(){};
util.inherits(resClass, mx);
util.inherits(resClass, cl);
return resClass;
}
Как оформить сие добро в jsdoc не могу уверенно предложить. Но, могу с уверенностью сказать, может примиси и удобный для web инструмент (в браузере много стандартных классов, в которых можно расширять функционал: HTMLDocument, XMLHttpRequest), но в Node.JS я бы уверенно обходился бы без них, с базовым одноуровневым наследованием.
Так или иначе, все зависит от конкретной задачи.
+1
Заметил еще косяк, что потерял конструктор. Правильнее было бы так:
var SecurityClient = mixClass(Client, Security);
function mixClass(cl, mx) {
var resClass = cl.prototype.constructor;
util.inherits(resClass, mx);
util.inherits(resClass, cl);
return resClass;
}
0
Не использовать фабрики в js очень большие жертвы. Кстати, можно даже сделать фабрику фабрик, таким образом экранировать класс провайдера от модификации и избавиться от new.
0
Sign up to leave a comment.
Node.JS Загрузка модулей по требованию