setInterval 中的 Promise

Promises inside a setInterval

我有一个 setInterval 每秒 运行 一个承诺,在每个承诺的 then 函数中,我将输出放入 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 秒的间隔在 search/insert 序列的连续调用之间施加延迟。这没有什么根本性的错误,但它不能保证每一步都在下一步开始之前完成,也不能保证下一步会尽快开始。在每一步,1秒的延迟可能绰绰有余,也可能不够,你真的不知道。

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

从一个数组开始,一个经过良好尝试的 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());

整个缩减过程returns一个承诺,它本身可以返回and/or与其他承诺聚合。