Как можно улучшить/оптимизировать код node.js?
Нужна помощь по оптимизации кода на node.js. Сейчас он довольно "ужасный", хотел бы узнать совет специалистов, где можно улучшить.
Ссылка: plnkr.co/edit/EpZ8qDecDIuJ6Xdb?open=lib%2Fscript.js
const cron = require('node-cron')
const Platform = require('../db/models')
const UpDown = require('../db/models/platform/easy/upDown')
const User = require('../db/models/user')
class Easy {
constructor(name, balance, nameTranslate, data, activeDeals, history, watchPeople, maxDataLength, min, max) {
this.name = name
this.title= '1:2'
this.coefficient = 2
this.balancePlatform = balance // общий баланс игры
this.data = {
name: nameTranslate,
data: data, //данные, которые меняются каждую секунду
activeDeals: activeDeals, //данные, от которых зависит изменение свойства каждую секунду
history: [],
watchPeople: watchPeople, // кол-во посетителей в данный момент
maxDataLength: maxDataLength, // максимальное количество данных в data.data
min: min, // минимальный Y
max: max, // максимальный Y
dataLength: 0,
rate: 2 // коэфициент
}
} //
/* getters */
get firstSide() { //первая сторона
return this.searchSides(true)
}
get firstSideNumberUsers() { // подсчет юзеров на одну сторону
return this.searchSidesNumberUsers(true)
}
get lastSide() { // вторая сторона
return this.searchSides(false)
}
get lastSideNumberUsers() {
return this.searchSidesNumberUsers(false)
}
get statusPlatform() {
if (this.firstSideNumberUsers && this.lastSideNumberUsers) {
return 'online'
}
if (
(this.firstSideNumberUsers > 0 && this.lastSideNumberUsers === 0)
||
(this.firstSideNumberUsers === 0 && this.lastSideNumberUsers > 0)
) {
return 'platform'
}
if (this.firstSideNumberUsers === 0 && this.lastSideNumberUsers === 0) {
return 'offline'
}
}
get sideStatus() {
if (this.statusPlatform === 'online') {
//ищем где сумма выше
if (this.firstSide > this.lastSide && this.firstSide != this.lastSide) {
return true
} else if (this.firstSide < this.lastSide && this.firstSide != this.lastSide) {
return false
} else {
return true
}
}
}
get returnData() {
return {
data: this.data.data, // массив данных, числа
activeDeals: this.data.activeDeals, // активные сделки
history: this.data.history, // история за весь день
watchPeople: this.data.watchPeople, // кол-во посетителей в данный момент
maxDataLength: this.data.maxDataLength,
min: this.data.min, // минимальный Y
max: this.data.max, // максимальный Y
dataLength: this.data.data.length
}
}
get searchSidesSum() { // количество суммы
if (this.data.activeDeals.length) {
return this.data.activeDeals.map(item => {
return item.sum
}).reduce((sum, item) => {
return sum + item
})
} else {
return 0
}
}
/* methods */
searchSides(dealType) { // количество суммы на сторону
return this.data.activeDeals.filter(item => {
return item.dealType === dealType
}).map(item => {
return item.sum
}).reduce((sum, item) => {
return sum + item
})
}
searchSidesNumberUsers(dealType) { //количество юзеров на сторону
return this.data.activeDeals.filter(item => {
return item.dealType === dealType
}).length
}
sortAsc(prev, next) {
return next.xOpen - prev.xOpen
}
sortDesc(prev, next) {
return prev.xOpen - next.xOpen
}
/* actions */
actionChart(min, max) { /* static logic */
let lastData = this.data.data[this.data.data.length - 1]
let generatedNumber = lastData + Math.round((Math.random() < 0.5 ? 1 : -1) * Math.random() * 5)
if (generatedNumber >= max) {
generatedNumber = lastData + Math.round(-1 * Math.random() * 5)
if (generatedNumber >= max) {
generatedNumber = max
}
}
if (generatedNumber <= min) {
generatedNumber = lastData + Math.round(1 * Math.random() * 5)
if (generatedNumber <= min) {
generatedNumber = min
}
}
if (generatedNumber >= max) {
generatedNumber = max
}
if (generatedNumber <= min) {
generatedNumber = min
}
this.data.data.push(+generatedNumber)
if (this.data.data.length > this.data.maxDataLength) {
this.data.data.splice(0, 1)
}
this.dataLength = this.data.data.length
// console.log(min, max)
}
actionChartPlatformOnline() {
if (this.searchSidesSum <= this.balancePlatform) {
this.actionChart(this.data.min, this.data.max)
} else {
let statusSearch = this.data.activeDeals.map(item => {
return item.dealType
})
let status = [...new Set(statusSearch)][0]
let mainCoords = 0
let sortUsers = []
let users = this.data.activeDeals.filter(item => {
return item.dealType === status
})
if (!status) {
sortUsers = users.sort(this.sortAsc)[0]
} else {
sortUsers = users.sort(this.sortDesc)[0]
}
mainCoords = sortUsers.xOpen
if (!status) {
this.actionChart(mainCoords + 1, this.data.max)
} else {
this.actionChart(this.data.min, mainCoords - 1)
}
}
}
actionChartOffline() { /* complete */
if (this.statusPlatform === 'offline') {
this.actionChart(this.data.min, this.data.max)
}
}
actionChartOnlineUpDown() { /* complete */
if (this.statusPlatform === 'online') {
this.actionChartPlatformOnline()
}
}
actionChartPlatform() { /* complete */
if (this.statusPlatform === 'platform') {
this.actionChartPlatformOnline()
}
}
action() {
this.actionChartOffline()
this.actionChartOnlineUpDown()
this.actionChartPlatform()
}
}
// Вот тут самое непонятное в улучшении производительности
// инициализируем класс игры с начальными данными
let modelUpDown = new Easy(
'upDown',
0,
'Выше/ниже',
[],
[],
[],
0,
0,
0,
0,
0
)
let actionCompute = () => { // функция, которая запускается каждую секунду..
Platform.findOne({}, (errBal, resBal) => { // поиск данных платформы (раз запрос)
UpDown.findOne({}, (err, res) => { // поиск игры (два запрос)
let chart = res.dataData
if (!res.dataData.length) chart = [+(res.dataMax / 2)]
modelUpDown.name = 'upDown'
modelUpDown.balancePlatform = resBal.balance
modelUpDown.data.name = 'Trade'
modelUpDown.data.data = chart
modelUpDown.data.activeDeals = res.dataActiveDeals //kill
modelUpDown.data.history = res.dataHistory //kill done
modelUpDown.data.watchPeople = res.dataWatchPeople
modelUpDown.data.maxDataLength = res.dataMaxDataLength
modelUpDown.data.max = res.dataMax
modelUpDown.data.min = res.dataMin
modelUpDown.data.dataLength = res.dataLength
// перезаписываем класс на данные и БД
//запускаем игру
modelUpDown.action()
// продумываем действия для игры
let addToBaseData = modelUpDown.returnData
let activeDeals = addToBaseData.activeDeals //берем актуальные данные
activeDeals.forEach((item, i) => { //ставим статусы
item.disable = false
item.xClose = addToBaseData.data[addToBaseData.data.length - 1]
if (item.dealType) { //если вверх
if (item.xClose > item.xOpen) {
item.status = true
} else {
item.status = false
}
} else {
if (item.xClose < item.xOpen) {
item.status = true
} else {
item.status = false
}
}
if (new Date() >= new Date(item.dealClose)) {
item.disable = true
}
})
let notActivities = activeDeals.filter(item => {
return item.disable
})
let activities = activeDeals.filter(item => {
return !item.disable
})
let buildNotActivities = res.dataHistory.concat(notActivities)
//ищем юзеров, которые учавствуют в игре и отдаем данные в их аккаунт
if (notActivities.length) {
notActivities.forEach((item, i) => {
User.updateOne( //3 запрос
{ id: item.id },
{
$push: {
dealsHistory: {
name: 'Trade',
idDeal: item.idDeal,
dealOpen: item.dealOpen,
dealClose: item.dealClose,
xOpen: item.xOpen,
xClose: item.xClose,
sum: item.sum,
status: item.status,
dealType: item.dealType
}
},
$inc: {
balance: (item.status) ? item.sum * 2 : 0
}
},
() => {})
})
}
//перезаписываем базу данных игры на новые данные
let app = UpDown.updateOne( //4 запрос
{ name: 'upDown', title: '1:2' },
{
$set:
{
dataData: addToBaseData.data,
dataActiveDeals: activities,
dataNotActivities: notActivities,
dataHistory: [],
dataWatchPeople: addToBaseData.watchPeople,
dataMaxDataLength: addToBaseData.maxDataLength,
dataMin: addToBaseData.min,
dataMax: addToBaseData.max,
dataLength: addToBaseData.dataLength
}
},
{
multi: true
},
(err, res) => {
if (err) return false
}
)
})
})
}
const app = cron.schedule('*/1 * * * * *', () => {
//запуск функции каждую секунду
actionCompute()
})
module.exports = app
В общем, понимаю, что максимально неправильно делать 4 запроса в бд + обработать и всё это за одну секунду. Можете что-нибудь посоветовать, как это исправить? потому что при добавлении новых данных начинает всё лагать, что не удивительно. Делать действие каждую секунду нужно обязательно, но может есть другой вариант помимо cron? от setTimeout всё с ума сходит.
Буду благодарен за любой совет и помощь!