Amb*_*mps 5 javascript node.js promise
我是Promises的新手,我想知道最佳做法是在保持变量的同时保持变量?
通过Promise连接到MongoDB非常简单:
connectToMongoDB(data).done(function(db) {
var collection = db.collection('test_inserts');
// do more stuff here
});
Run Code Online (Sandbox Code Playgroud)
但是,如果我必须连接到两个不同的数据库会发生什么?
connectToMongoDB1(data1).then(function(db1) {
return connectToMongoDB2(data2);
}).done(function(db2) {
var collection = db1.collection('test_inserts');
// ERROR: db1 is undefined
});
Run Code Online (Sandbox Code Playgroud)
这个错误非常有意义.但是如何在db1不改变我的connectToMongoDB2()功能的情况下前进,因为我想要保持connectToMongoDB2()并且我的所有承诺一般都非常通用?
我的意思是,我可以包装一个存储所有相关内容的对象,但这看起来有点像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
});
Run Code Online (Sandbox Code Playgroud)
什么是最佳做法?
Flo*_*ine 12
注意:我在这个答案中使用蓝鸟.
有三种方法可以做你想要的:闭包,绑定和Promise.using.
封闭是@Sukima展示的方式.
function promisedFunc() {
var db;
return getCollection().then(function(col) {
db = col;
return db.query(stuff);
}).then(function() {
return db.query(otherStuff);
});
}
Run Code Online (Sandbox Code Playgroud)
绑定:使用Promise.bind,您可以创建this一个包含值的对象.
function promisedFunc() {
return getCollection().bind({}).then(function(col) {
this.db = col;
return this.db.query(stuff);
}).then(function() {
return this.db.query(otherStuff);
});
}
Run Code Online (Sandbox Code Playgroud)
最后,bluebird v2引入的最后一种方法是使用真正的资源管理.
function promisedFunc() {
return Promise.using(getDb(), function(db) {
return db.query(stuff).then(function() {
return db.query(otherStuff);
});
});
}
Run Code Online (Sandbox Code Playgroud)
我将getDb进一步解释这个方法.
最后一种方式提供了另一个非常有趣的好处:处理资源.例如,您经常需要close为数据库资源调用方法.Promise.using让你创建处理器,一旦解决(或不解决)其中的承诺就运行.
要了解为什么这是一个优势,让我们回顾一下这3种方法.
关闭:
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();
});
Run Code Online (Sandbox Code Playgroud)
是的,这意味着每次使用数据库连接时都必须编写所有这些样板文件.别无选择.
现在让我们看看绑定方式:
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();
});
Run Code Online (Sandbox Code Playgroud)
然而,现在,这可以模块化.
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);
Run Code Online (Sandbox Code Playgroud)
这已经好多了!但我们仍然需要考虑使用finally.
然后,蓝鸟引入的方式,Promise.using.通过这种方式声明:
function getDb() {
var close;
return getCollection().spread(function(db, done) {
close = done;
return db;
}).disposer(function() {
close();
});
}
Run Code Online (Sandbox Code Playgroud)
您可以像以前一样使用它:
return Promise.using(getDb(), function(db) {
return db.query(stuff).then(function() {
return db.query(otherStuff);
});
});
Run Code Online (Sandbox Code Playgroud)
无需考虑finally,也没有样板.