Connorelsea Connorelsea - 7 months ago 22
SQL Question

ES6 Promises run out of order when using Node-MySQL

Why does this series of promises run out of order? The "object" object in the final .then block is undefined at runtime.

new Promise(function(resolve, reject) {

getConnection().query("SELECT * FROM blog", (err, rows) => {
if (err) reject(err)
else resolve(rows)
})

}).then(rows => {

let posts = []

for (let i = 0; i < rows.length; i++) {
posts.push({
id: rows[i].id,
...
})
}

return posts

}).then(posts => {

getConnection().query("SELECT * FROM shows", (err, rows) => {
if (err) throw new Error(err)
else return { posts: posts, shows: rows }
})

}).then(object => {

let posts = object.posts

let post_container = { my: [], your: [] }

post_container.my = posts.filter(x => x.section === "my")
post_container.your = posts.filter(x => x.section === "your")

return post_container

})

Answer

Your return in

.then(posts => {

    getConnection().query("SELECT * FROM shows", (err, rows) => {
        if (err) throw new Error(err)
        else return { posts: posts, shows: rows }
    })

})

...returns from the query callback, not the then callback; that return value is completely ignored. Since there's no explicit return in the then callback, it returns a promise resolved with undefined and so the following then callback is called with undefined (and before the async work above is done).

You need to return either a value to use immediately or a promise from the then callback; since your code in the then callback is asynchronous, you'll want to return a promise that you settle when the async work is complete, so:

.then(posts => {
    return new Promise((resolve, reject) => {
        getConnection().query("SELECT * FROM shows", (err, rows) => {
            if (err) reject(/*...reject reason...*/)
            else resolve({ posts: posts, shows: rows })
        })
    })
})

You might look at one of the libs that promise-ifies NodeJS callbacks so you can use promises more directly in your code. There are at least a couple, and then you could use the promise a promise-ified query gave you rather than having to create your own each time.