Promises inside a setInterval

Promises inside a setInterval

本文关键字:setInterval inside Promises      更新时间:2023-09-26

我有一个setInterval,它每秒运行一个promise,在每个promise的then函数中,我将输出放入MongoDB数据库中(尽管由于某些原因它不起作用)。

我想在所有事情都完成后关闭与数据库的连接,但我不知道如何使连接的关闭只在所有承诺都完成并且所有事情都已写入数据库时运行。

这是我当前的代码:

我有一个client.js文件,用于使用promise向商店发出查询,还有一个db.js,用于处理DB功能。

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秒的间隔来在搜索/插入序列的连续调用之间施加延迟。这并没有什么根本性的错误,但它不能保证每一步都在下一步开始之前完成,也不能保证下一步尽快开始。在每一步中,1秒的延迟可能绰绰有余,也可能不足,你真的不知道。

幸运的是,promise提供了一种更好的方法来处理异步。

从一个数组开始,一个久经考验的reduce模式是可用的(请参阅此处的"收集混乱"以强加一个序列:

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

整个减少过程返回一个承诺,该承诺本身可以返回和/或与其他承诺聚合。