setInterval中的promise

时间:2016-01-12 22:14:53

标签: javascript node.js mongodb promise setinterval

我有一个setInterval每秒运行一个承诺,在每个承诺的函数中,我将输出放入MongoDB数据库(虽然由于某种原因它不能正常工作)。

我希望在完成所有工作后关闭与数据库的连接,但我不知道如何在所有承诺完成并且所有内容都已写入数据库后运行连接关闭。

这是我目前的代码:

我有一个client.js文件,用于向商店发出查询,使用承诺和db.js,用于处理数据库功能。

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();
}

此外,由于我对JavaScript和Node.js一般都是新手,所以我们将非常感谢任何最佳做法或一般提示! :)

1 个答案:

答案 0 :(得分:4)

如上所述,您依靠1秒间隔在连续调用搜索/插入序列之间施加延迟。这并没有什么根本性的错误,但并不能保证每一步都在下一步开始之前完成,并且不能保证下一步尽快开始。在每一步,1秒的延迟可能绰绰有余或不足,你真的不知道。

幸运的是,承诺提供了一种更好的方法来应对异步。

从数组开始,可以使用经过良好尝试的reduce模式(请参阅“The Collection Kerfuffle”here以强制执行序列:

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

其中Promise是ES6的原生Promise,或者例如Bluebird。

对于问题中的代码,doSomethingAsync()部分展开为:

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());

整个还原过程返回一个承诺,它本身可以返回和/或与其他承诺汇总。