使用Promise时挂起变量的最佳实践 [英] Best practice to hang on to variables when using Promises

查看:113
本文介绍了使用Promise时挂起变量的最佳实践的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是Promises的新手,我想知道最佳做法是在保持变量的同时保持变量吗?

I am new to Promises and I was wondering what the best practice is to keep variables while going down the chain?

通过Promise连接到MongoDB非常简单:

Connecting to MongoDB via Promise is pretty straight forward:

connectToMongoDB(data).done(function(db) {

    var collection = db.collection('test_inserts');
    // do more stuff here

});

但如果我必须连接到两个不同的数据库会怎样?

But what happens if I have to connect to two different databases?

connectToMongoDB1(data1).then(function(db1) {

    return connectToMongoDB2(data2);

}).done(function(db2) {

    var collection = db1.collection('test_inserts');
    // ERROR: db1 is undefined

});

这个错误很有意义。但是如何转发 db1 而不改变我的 connectToMongoDB2()函数,因为我想保留 connectToMongoDB2()我所有的承诺一般都非常通用吗?

That error makes perfect sense. But how do I forward db1 without altering my connectToMongoDB2() function, because I want to keep connectToMongoDB2() and all my promises in general very generic?

我的意思是,我可以包装一个对象来存储所有相关的东西,但这看起来有点hacky:

I mean, I could wrap an object around that stores all the relevant stuff, but that looks kind of hacky:

var relevantStuff = {};

connectToMongoDB1(data1).then(function(db1) {

    relevantStuff.db1 = db1;
    return connectToMongoDB2(data2);

}).done(function(db2) {

    var collection = relevantStuff.db1.collection('test_inserts');
    // do more stuff here

});

什么是最佳做法?

推荐答案

注意:我正在使用 bluebird 在这个答案中。

Note: I'm using bluebird in this answer.

有3种方法可以做你想要的:闭包,绑定和 Promise.using

There are 3 ways to do what you want: closures, binding, and Promise.using.

关闭是@Sukima展示的方式。

Closure is the way @Sukima showed.

function promisedFunc() {
    var db;
    return getCollection().then(function(col) {
        db = col;
        return db.query(stuff);
    }).then(function() {
        return db.query(otherStuff);
    });
}

绑定:使用 Promise.bind ,你可以使这个一个保存值的对象。

Binding: using Promise.bind, you can make this an object that will hold values.

function promisedFunc() {
    return getCollection().bind({}).then(function(col) {
        this.db = col;
        return this.db.query(stuff);
    }).then(function() {
        return this.db.query(otherStuff);
    });
}

终于,蓝鸟推出的最后一种方式v2,正在使用真实资源管理。

Finally, the last way, introduced by bluebird v2, is using real resource management.

function promisedFunc() {
    return Promise.using(getDb(), function(db) {
        return db.query(stuff).then(function() {
            return db.query(otherStuff);
        });
    });
}

我要解释 getDb 方法进一步向下。

I'm going to explain the getDb method further down.

最后一种方式提供了另一个非常有趣的好处:处置资源。例如,您经常需要为数据库资源调用 close 方法。 Promise.using 可让您创建处理器,一旦解决(或不解决)其中的承诺就会运行。

The last way provides another very interesting benefit: disposing resources. For example, you often have to call a close method for database resources. Promise.using lets you create disposers, running once the promises in it are resolved (or not).

To看看为什么这是一个优势,让我们回顾一下这3种方法。

To see why this is an advantage, let's review the 3 ways to do this.

关闭:

var db, close;
return getCollection().spread(function(col, done) {
    db = col;
    close = done;
    return db.query(stuff);
}).then(function() {
    return db.query(otherStuff);
}).finally(function() {
    close();
});

是的,这意味着每次使用数据库时都必须编写所有这些样板文件连接即可。别无选择。

And yes, it means you have to write all this boilerplate every time you use the db connection. No other choice.

现在让我们看看绑定方式:

Now let's see the binding way:

return getCollection().bind({}).spread(function(col, done) {
    this.db = col;
    this.close = done;
    return this.db.query(stuff);
}).then(function() {
    return this.db.query(otherStuff);
}).finally(function() {
    this.close();
});

然而,现在可以模块化。

Now however, this can be modularized.

var db = {
    getDb: function() { return getCollection().bind({}); },
    close: function() { this.close(); }
};

return db.getDb().then(function() {
    return this.db.query(stuff);
}).then(function() {
    return this.db.query(otherStuff);
}).finally(db.close);

这已经好多了!但我们仍然要考虑使用最后

This is already a lot nicer! But we still have to think about using finally.

然后,bluebird引入的方式, Promise.using 。通过这种方式声明:

And then, the way introduced by bluebird, Promise.using. By declaring it this way:

function getDb() {
    var close;
    return getCollection().spread(function(db, done) {
        close = done;
        return db;
    }).disposer(function() {
        close();
    });
}

您可以像以前一样使用它:

You can simply use it as seen before:

return Promise.using(getDb(), function(db) {
    return db.query(stuff).then(function() {
        return db.query(otherStuff);
    });
});

无需考虑最后,以及没有样板。

No need to think about finally, and no boilerplate.

这篇关于使用Promise时挂起变量的最佳实践的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆