最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Promises inside a setInterval - Stack Overflow

programmeradmin0浏览0评论

I've got a setInterval that runs a promise every second, inside the then function of every promise, I put the output into a MongoDB database (although for some reason it's not working).

I want to close the connection to the database when everything is done, but I don't know how to to make the closing of the connection only run when all promises are done and everything has finished writing to the DB.

Here is my current code:

I've got a client.js file, meant to issue the query to a shop, using a promise, and a db.js, meant to handle DB functionality.

client.js

var id = setInterval(function(){

        if (i == (categories.length-1))
            clearInterval(id);


            var category = categories[i];

            client.itemSearch({  
              searchIndex: SearchIndex,
              categoryID: category.id,
              keywords: currentKeyword
            })
            .then(function(results){

                var title = results[0].Title;
                var cat = category.name;
                var price = results[0].Price

                db.insertProduct(title,cat,price).then(function(){
                    console.log("Added " + title);
                })
            },function(err) {
                console.log("error at " + category.name);
            });
            i+=1;
    }, 1000)

queryStore();

db.js

var mongoose = require("mongoose");

mongoose.connect('mongodb://localhost:27017/catalog');

var schema = new mongoose.Schema({
    title           : String,
    category        : String,
    price           : Number,
}, {collection: "catalog"});

var Product = mongoose.model("Product", schema);

Product.remove({}, function() {
    console.log('Database cleared.') 
});


exports.clearDB = function() {
    Product.remove({});
}

exports.insertProduct = function (Title,Category,Price) {
    var entry = new Product({
        title: Title,
        category: Category,
        price: Price,
    });

    entry.save();
}

exports.closeConn = function() {
    console.log("Closing DB Connection");
    mongoose.connect().close();
}

Also, since I'm absolutely new to JavaScript and Node.js in general, any best practices or general tips will be greatly appreciated! :)

I've got a setInterval that runs a promise every second, inside the then function of every promise, I put the output into a MongoDB database (although for some reason it's not working).

I want to close the connection to the database when everything is done, but I don't know how to to make the closing of the connection only run when all promises are done and everything has finished writing to the DB.

Here is my current code:

I've got a client.js file, meant to issue the query to a shop, using a promise, and a db.js, meant to handle DB functionality.

client.js

var id = setInterval(function(){

        if (i == (categories.length-1))
            clearInterval(id);


            var category = categories[i];

            client.itemSearch({  
              searchIndex: SearchIndex,
              categoryID: category.id,
              keywords: currentKeyword
            })
            .then(function(results){

                var title = results[0].Title;
                var cat = category.name;
                var price = results[0].Price

                db.insertProduct(title,cat,price).then(function(){
                    console.log("Added " + title);
                })
            },function(err) {
                console.log("error at " + category.name);
            });
            i+=1;
    }, 1000)

queryStore();

db.js

var mongoose = require("mongoose");

mongoose.connect('mongodb://localhost:27017/catalog');

var schema = new mongoose.Schema({
    title           : String,
    category        : String,
    price           : Number,
}, {collection: "catalog"});

var Product = mongoose.model("Product", schema);

Product.remove({}, function() {
    console.log('Database cleared.') 
});


exports.clearDB = function() {
    Product.remove({});
}

exports.insertProduct = function (Title,Category,Price) {
    var entry = new Product({
        title: Title,
        category: Category,
        price: Price,
    });

    entry.save();
}

exports.closeConn = function() {
    console.log("Closing DB Connection");
    mongoose.connect().close();
}

Also, since I'm absolutely new to JavaScript and Node.js in general, any best practices or general tips will be greatly appreciated! :)

Share Improve this question edited Jan 12, 2016 at 22:52 J0e3gan 8,95810 gold badges57 silver badges81 bronze badges asked Jan 12, 2016 at 22:14 DaedalusDaedalus 3051 gold badge6 silver badges15 bronze badges 4
  • 1 Promises are not "run", they only are created. – Bergi Commented Jan 12, 2016 at 22:22
  • 1 I really remend not to use setInterval together with promises. Promisify setTimeout and only use that. – Bergi Commented Jan 12, 2016 at 22:22
  • @Bergi could you elaborate? I'm not sure I understand what that means – Daedalus Commented Jan 12, 2016 at 22:24
  • If you refer to my first ment, it's just about terminology. Promises are values, not something that can be executed. – Bergi Commented Jan 12, 2016 at 22:27
Add a ment  | 

1 Answer 1

Reset to default 4

As written you are relying on a 1 second interval to impose a delay between successive calls of a search/insert sequence. There's nothing fundamentally wrong with that but it doesn't guarantee that each step is plete before the next one starts, and doesn't guarantee that the next step starts as soon as possible. At each step, the 1 second delay may be more than adequate or less than adequate, you don't really know.

Fortunately, promises offer a much better way to cope with the asynchronism.

Starting with an array, a well tried reduce pattern is available (see "The Collection Kerfuffle" here to impose a sequence :

array.reduce(function(promise, item) {
    return promise.then(function() {
        return doSomethingAsync(item);
    });
}, Promise.resolve());

where Promise is ES6's native Promise, or eg Bluebird.

For the code in the question, the doSomethingAsync() part expands to give :

categories.reduce(function(promise, category) {
    return promise.then(function() {
        return client.itemSearch({
            'searchIndex': SearchIndex,
            'categoryID': category.id,
            'keywords': currentKeyword
        }).then(function(results) {
            var title = results[0].Title;
            var cat = category.name;
            var price = results[0].Price;
            return db.insertProduct(title, cat, price);
        }).then(function() {
            console.log("Added " + title);
        }).catch(function(err) {
            console.log("error at " + category.name);
        });
    });
}, Promise.resolve());

The entire reduction process returns a promise, which can itself be returned and/or aggregated with other promises.

发布评论

评论列表(0)

  1. 暂无评论