0

The code below is one of the middlewares in my application, and what it does is that when a user send post request to the server, it saves the form data to engines table and then loads all related engines data to extract average values to insert new data to the corresponding rocket in rockets table. Although it works, apparently my code is so unnecessarily nested(I think) and verbose since I am not familiar with promises..

  1. How could I write better code or at least simplify a little from it?
  2. One thing I don't understand from the code is in the comment line.
  3. Thank you.

const express = require('express');
const app = express();
const logger = require('morgan');
const knex = require('./db/index.js');
const bodyParser = require('body-parser');
const { check, validationResult, body } = require('express-validator/check')
app.use(logger(':method :url :status :date[clf]'));
app.use(express.static("public"));
app.use(bodyParser.json());



app.post('/engines/:id', (req, res) => {
    knex('engines').insert({ 
        rocket_id: req.params.id,
        user_id: 1,
        price: req.body.price,
        shining: req.body.shining,
        texture: req.body.texture,
        modern: req.body.modern,
        hardness: req.body.hardness,
        loud: req.body.loud,
        power: req.body.power,
        explosion_risk: req.body.explosion_risk
    }).then( () => {
        const rocket_temp = {};
        return rocket_temp;
    }).then( rocket_temp => {
        const knexWhere = knex('engines').where({rocket_id: req.params.id});

        knexWhere.first().count('explosion_risk').then( data => {
            rocket_temp.total_count_risk = data.count;
            return rocket_temp;
        }).then( rocket_temp => {
            knexWhere.where({explosion_risk: true}).first().count('explosion_risk').then( data => {
                rocket_temp.countTrue = data.count;
                return rocket_temp;
            }).then( rocket_temp => {
                const knexWhere = knex('engines').where({rocket_id: req.params.id}); // I don't get why knexWhere variable must be re-assigned at this point. Otherwise it won't know that it should load data from 'evaluations' table. Simply saying, the value assigned to knexWhere variable is suddenly changed from this point.(Somehow it loads data from rockets table).

                knexWhere.first(knex.raw('ROUND(AVG(price))')).then( data => {
                    rocket_temp.avg_price = data.round;
                    return rocket_temp;
                }).then( rocket_temp => {
                    knexWhere.first(knex.raw('ROUND(AVG(shining))')).then( data => {
                        rocket_temp.avg_shining = data.round;
                        return rocket_temp;
                    }).then( rocket_temp => {
                        knexWhere.first(knex.raw('ROUND(AVG(texture))')).then( data => {
                            rocket_temp.avg_texture = data.round;
                            return rocket_temp;
                        }).then( rocket_temp => {
                            knexWhere.first(knex.raw('ROUND(AVG(modern))')).then( data => {
                                rocket_temp.avg_modern = data.round;
                                return rocket_temp;
                            }).then( rocket_temp => {
                                knexWhere.first(knex.raw('ROUND(AVG(hardness))')).then( data => {
                                    rocket_temp.avg_hardness = data.round;
                                    return rocket_temp;    
                                }).then( rocket_temp => {
                                    knexWhere.first(knex.raw('ROUND(AVG(loud))')).then( data => {
                                        rocket_temp.avg_loud = data.round;
                                        return rocket_temp;    
                                    }).then( rocket_temp => {
                                        knexWhere.first(knex.raw('ROUND(AVG(power))')).then( data => {
                                            rocket_temp.avg_power = data.round;
                                            return rocket_temp;
                                        }).then( rocket_temp => {
                                            
                                            knex('rockets').where({id: req.params.id}).first().update({
                                                price: rocket_temp.avg_price,
                                                shining: rocket_temp.avg_shining,
                                                texture: rocket_temp.avg_texture,
                                                modern: rocket_temp.avg_modern,
                                                hardness: rocket_temp.avg_hardness,
                                                loud: rocket_temp.avg_loud,
                                                power: rocket_temp.avg_power,
                                                explosion_risk: Math.round(parseInt(rocket_temp.countTrue)/parseInt(rocket_temp.total_count_risk) * 100)
                                            }).then( res => {
                                                knex('rockets').select().then( res => console.log(res) )
                                            })
                                        })
                                    })
                                })
                            })
                        })
                    })
                })
            })
        })                            
    }).then( result => res.sendStatus(201) );
})

   
Jay Jeong
  • 892
  • 2
  • 11
  • 24
  • `return` all the `Promise`s instead and chain them on the same indentation level. eg `return knexWhere.first() ...` – CertainPerformance Jun 21 '18 at 05:37
  • 1
    I don't see any reason why all these queries can't be run in parallel either. Wrap each of them in a `Promise.all()` so they can all run in the background simultaneously rather than sequentially. – Patrick Roberts Jun 21 '18 at 05:42
  • seems an odd choice for duplicate - considering there doesn't seem to be **any** explicit promise construction going on!! – Jaromanda X Jun 21 '18 at 06:00
  • perhaps something like https://pastebin.com/0igCa0jV – Jaromanda X Jun 21 '18 at 06:09
  • dang, thanks to all, especially Jaromanda X for refactoring all that code. It is definitely a way better code. – Jay Jeong Jun 21 '18 at 07:03
  • @JaromandaX just one more question, you wrote a comment that says put the statements for explosion_risk's count as last entries. Why is that ? Why this works in this way? – Jay Jeong Jun 21 '18 at 10:58
  • it's probably the second `knexWhere.where` that mucks you about - I don't know knex, at all – Jaromanda X Jun 21 '18 at 11:37

0 Answers0