简体   繁体   中英

Sequelize JS node updating multiple entities with new data from previous promise

I am new to sequelize and NodeJS promises in general. My app basically saves tweets from the Twitter API, but also needs to update some of the saved tweets' data in realtime, like the Retweet count or the Liked count.

But it seems like after fetching the new data, when trying to run all the update on my tweet instances, nothing happens. The promise doesn't go through.

To sum up : I find 100 saved tweets, chain on a callback that fetches their new data from Twitter, and then chain on updating every single 100 tweets with the new data. The later update doesn't go through.

 var Sequelize = require('sequelize'); ... //Getting 100 tweets previously saved in DB Sequelize.query("SELECT * FROM tweets WHERE ORDER BY id DESC LIMIT 100", { model: Model }).then(function(result) { if(result.length == 0) { callback(false); } else { var ids = []; var realData = {}; for (var i in result) { realData[result[i].dataValues.id_str] = result[i]; ids.push(result[i].dataValues.id_str); } //getting twitter data for 100 tweets previously saved in DB twitVendor.get('statuses/lookup', { id : ids.join(',') }, function (err, tweets, response) { if (typeof err == 'undefined') { //to get a synchronous saving of all tweets //this could be cleaned up with a Sequelize.Promise.push(...) var i = 0; var saving = false; while (i < tweets.length) { if (!saving) { saving = true; console.log('Updating tweet ', tweets[i].id_str); //updating tweet with new data from twitter Sequelize.query("UPDATE tweets SET retweet_count = "+tweets[i].retweet_count+", favorite_count = "+tweets[i].favorite_count+" WHERE id_str = '"+tweets[i].id_str+"'", { model: Model }).then(function(result) { console.log('Updated tweet'); saving = false; i++; }).catch(function (err) { console.log('Failed to update post ', err); saving = false; i++; }); } } callback(true); console.log("Updated tweets"); } else { console.log("Failed :", err); callback(false, err); } }); } }).catch(function (err) { console.log("Failed :", err); callback(false, err); }) 

EDIT : If you want to execute the above code, I'd recommend using this Twit to hit the Twitter API : https://github.com/ttezel/twit

To get credentials to hit the API, you will need to set up an app on Twitter though : https://apps.twitter.com/

EDIT 2 : I already tried to use transactions and pure Sequelize functions to make my queries, but the issue stood still.

Don't nest promises inside of promises. Instead, chain them by returning promises. If you are returning something that is not a promise, use Promise.resolve(value) to turn it into a promise. And certainly don't put promises inside of callbacks, or even mix them at all; instead create a promise that calls the action, and then in the callback resolve the promise.

Here's my attempt to rewrite what you're trying to do. You may need to wrap the first in a Promise.resolve to take advantage of returning the new promise:

Sequelize.query("SELECT * FROM tweets WHERE ORDER BY id DESC LIMIT 100"
    , { model: Model }).then(function (results) {
    if (results.length == 0) {
        return Promise.reject(false); //reject to hit the catch of the promise. Change false to error.
    }
    var ids = [];
    var realData = {};

    for (var i in result) {
        realData[result[i].dataValues.id_str] = result[i];
        ids.push(result[i].dataValues.id_str);
    }

    return new Promise((resolve, reject) => {
        twitVendor.get('status/lookup', {
            id: ids.join(',')
        }, function (err, tweets, response) {
            if (err) {
                reject(false); //reject to hit the catch of the promise. Change false to error message
            }
            resolve(tweets);
        })
    })
}).then(function (tweets) {
    function updateTweet(tweet) {
        return sequelize.query(...);
    }

    var updatesInParallel = tweets.map(updateTweet);

    return Promise.all([updatesInParallel]);
}).then(function () {
    callback(true);
}).catch(function (error) {
    console.log("failed: ", error);
    callback(false)
});

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