节点承诺;记住每个(顺序)步骤的结果

Node promises; remember result of each (sequential) step

我想用节点的 Q 库做两件事。

1)发出多个异步查询,每一个都使用前一个的结果,并且 2) 一旦全部完成,就可以一次访问每个查询的结果

例如假设一个数据库有 ridings,每个 ridings 有一个城市,每个有一个 state,每个有一个 country。给定一次骑行,我想一次打印出所有这些地理数据。

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 :(
    })

通过这种模式,我可以访问所有数据,但不能同时访问。

什么被认为是一次获取所有数据的干净、传统的模式??

我多次看到的一种简单方法是逐步写入位于周围范围内的对象,然后从 promise 链末尾的对象读取:

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