简体   繁体   中英

Is there a way to be more concise when using classMethods in Sequelize?

I have a model intent which has a hasMany association to conditions and links and nodes . The nodes themselves have an association to links as well.

Through an express route I want to get all that information in one object. The way I have done it now is very callbackery and unreadable. It works, but I'm hoping there's a better way to write these kind of things.

app.get('/api/intents/:id', function(req, res) {
    models.intent.findOne({
        where: {
            id: req.params.id
        }
    })
    .then(function(intent) {
        intent.getConditions() // call generated function from intent model for conditions
        .then(function(conditions) {
            intent.getLinks() // then call generated function from intent model for links
            .then(function(links) {
                intent.getNodes() // then call generated function from nodes model for links
                .then(function(nodes) {
                    Promise.map(nodes, function(node) {
                        return node.getLinks() // Even deeper nested and getting out of hand
                        .then(function(links) {
                            node.setDataValue('links', links)
                        })
                    })
                    .then(function() {
                        intent.setDataValue('conditions', conditions)
                        intent.setDataValue('links', links)
                        intent.setDataValue('nodes', nodes)
                        res.json(intent)
                    })
                })
            })
        })
    })
})

I think that you totally missed the conception of include in options object of method like findOne . Just use

models.intent.findById(req.params.id, {
    include: [
        { model: models.condition },
        { model: models.link },
        { model: models.node, include: [ { model: models.link } ]
    ]
}).then((intent) => {
    // here you get intent with conditions, links and nodes with links
});

Other way is to define and use scopes on models.

You can use Promise.all() to wait for all the promises to be resolved and then do something with the data.

Below is a partial example to get you on track:

app.get('/api/intents/:id', function(req, res) {
models.intent.findOne({
    where: {
        id: req.params.id
    }
})
.then(function(intent) {
    let promises = []

    promises.push(intent.getConditions())
    promises.push(intent.getLinks())
    promises.push(intent.getNodes())

    Promise.all(promises)
    .then(function(resolvedPromises) {
        Promise.map(resolvedPromises, function(node) {
            intent.setDataValue('conditions', resolvedPromises[0])
            intent.setDataValue('links', resolvedPromises[1])
            ...
        })
    })
})

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM