Javascript 节点承诺;记住每个(连续)步骤的结果
我想用节点的Javascript 节点承诺;记住每个(连续)步骤的结果,javascript,node.js,promise,q,Javascript,Node.js,Promise,Q,我想用节点的Q库做两件事 1) 发出多个异步查询,每个查询都使用前一个查询的结果,然后 2) 可以访问每个查询的结果,一次完成所有查询 例如,假设一个数据库有RIDING,每个RIDING都有一个城市,每个RIDING都有一个州,每个RIDING都有一个国家。我想一次打印出所有这些地理数据 var ridingObj = // Already have access to this database object ridingObj.getRelated('city') .then(f
Q
库做两件事
1) 发出多个异步查询,每个查询都使用前一个查询的结果,然后
2) 可以访问每个查询的结果,一次完成所有查询
例如,假设一个数据库有RIDING,每个RIDING都有一个城市,每个RIDING都有一个州,每个RIDING都有一个国家。我想一次打印出所有这些地理数据
var ridingObj = // Already have access to this database object
ridingObj.getRelated('city')
.then(function(cityObj) {
// Have access to cityObj.getField('name');
return cityObj.getRelated('state');
})
.then(function(stateObj) {
// Have access to stateObj.getField('name');
return stateObj.getRelated('country');
})
.then(function(countryObj) {
// Have access to countryObj.getField('name');
// Can't console.log anything but the country, because we no longer have access :(
})
通过这种模式,我可以访问所有数据,但不能同时访问
一次获取所有数据的干净、常规模式是什么?我在多个场合见过的一种简单方法是逐步写入周围范围内的对象,然后从承诺链末端的对象读取:
var ridingObj = ...;
var result = {};
ridingObj.getRelated('city')
.then(function(cityObj) {
result.city = cityObj; // write city
return cityObj.getRelated('state');
})
.then(function(stateObj) {
result.state = stateObj; // write state
return stateObj.getRelated('country');
})
.then(function(countryObj) {
result.country = countryObj; // write country
console.log(result); // read all
})
我见过的一种在多种情况下都能做到的简单方法是逐步写入周围范围内的对象,然后从承诺链末端的对象读取:
var ridingObj = ...;
var result = {};
ridingObj.getRelated('city')
.then(function(cityObj) {
result.city = cityObj; // write city
return cityObj.getRelated('state');
})
.then(function(stateObj) {
result.state = stateObj; // write state
return stateObj.getRelated('country');
})
.then(function(countryObj) {
result.country = countryObj; // write country
console.log(result); // read all
})
我想出了一个很酷的办法 它使用了一个范围更大的变量,但它没有副作用,而且它允许您将所有结果作为函数的参数来访问,这看起来很干净
var p = queryForRiding();
Q.spread([
p,
p = p.then(function(riding) { return riding.getRelated('city'); }),
p = p.then(function(city) { return city.getRelated('state'); }),
p = p.then(function(state) { return state.getRelated('country'); })
], function(riding, city, state, country) {
console.log(riding, city, state, country);
});
我想出了一个很酷的办法 它使用了一个范围更大的变量,但它没有副作用,而且它允许您将所有结果作为函数的参数来访问,这看起来很干净
var p = queryForRiding();
Q.spread([
p,
p = p.then(function(riding) { return riding.getRelated('city'); }),
p = p.then(function(city) { return city.getRelated('state'); }),
p = p.then(function(state) { return state.getRelated('country'); })
], function(riding, city, state, country) {
console.log(riding, city, state, country);
});
太好了,我相信这会管用的!我正在寻找一种被认为是处理这种模式的“传统”方法——可以想象,这种方法可以避免更大范围的变量。我希望有一些漂亮的东西,包括
Q.spread
或类似的东西,但如果没有常规的方法,我会检查这个!我所能想到的每一次修改都会将结果
作为第二个参数传递给扩展
承诺链的每个阶段。它为链中的每个处理程序添加了更多的样板文件。我觉得这个答案很简单,不牺牲可读性和适应性。我想我已经找到了一个很好的方法来做到这一点,而且没有副作用。我正在发布我的答案,给我一些反馈,我会决定我们中的哪一个被接受!太好了,我相信这会管用的!我正在寻找一种被认为是处理这种模式的“传统”方法——可以想象,这种方法可以避免更大范围的变量。我希望有一些漂亮的东西,包括Q.spread
或类似的东西,但如果没有常规的方法,我会检查这个!我所能想到的每一次修改都会将结果
作为第二个参数传递给扩展
承诺链的每个阶段。它为链中的每个处理程序添加了更多的样板文件。我觉得这个答案很简单,不牺牲可读性和适应性。我想我已经找到了一个很好的方法来做到这一点,而且没有副作用。我正在发布我的答案,给我一些反馈,我会决定我们中的哪一个被接受!在es6中,您可以使用Promise.all()-我确信必须有一个与Q等效的函数。。。(但为什么不只是使用原生ES6功能,现在它在那里?)有一件事你可能要考虑的是,如果那些是数据库调用,你可能想立即做它们作为事务的一部分(取决于你正在使用的数据库- SQL连接或MangoDB填充)。执行4次数据库调用而不是1次将对性能产生相当大的影响,我相信您可以想象。。。。但如果你不能,我认为4castle的答案是最好的。它有“副作用”,看起来不干净,但我认为是最好的。尽管您正在触发顺序调用,但您的代码似乎对一次获得所有结果感兴趣。为什么它需要顺序?如果您一次获得所有结果而不进行连续调用,这样做可以吗?这只是一个示例!我实际上并没有使用数据库,所以我对连接不感兴趣。我对传统的promise模式感兴趣,它应该在以下情况下使用:1)一系列非阻塞函数需要按顺序执行,2)所有这些函数调用的结果需要同时访问。在es6中,您可以使用promise.all()-我确信Q必须有一个等价物。。。(但为什么不只是使用原生ES6功能,现在它在那里?)有一件事你可能要考虑的是,如果那些是数据库调用,你可能想立即做它们作为事务的一部分(取决于你正在使用的数据库- SQL连接或MangoDB填充)。执行4次数据库调用而不是1次将对性能产生相当大的影响,我相信您可以想象。。。。但如果你不能,我认为4castle的答案是最好的。它有“副作用”,看起来不干净,但我认为是最好的。尽管您正在触发顺序调用,但您的代码似乎对一次获得所有结果感兴趣。为什么它需要顺序?如果您一次获得所有结果而不进行连续调用,这样做可以吗?这只是一个示例!我实际上并没有使用数据库,所以我对连接不感兴趣。我感兴趣的是当1)一系列非阻塞函数需要按顺序执行时,以及2)所有这些函数调用的结果需要同时访问时,应该使用的传统承诺模式。中详细探讨了整个主题。这个答案是“打破链条”的一个例子。整个主题在中得到了很好的探讨。这个答案是“断链”的一个例子。