2015-10-24 98 views
0

这一整天我试图围绕这个问题来解决我的问题。数据库表的客户端异步连接

我想从一个sqljite数据库中,从一个angularJS应用程序,使用nodejs作为运行从客户端生成SQL查询的垫片提取一个实体树。我也使用underscore.js。

我可以通过使用连接并将行膨胀到嵌套对象和数组客户端,将实体扁平化为类表结构(不包含其他对象的对象的数组),但是我想了解承诺。我可以使用Hibernate和JPA的Spring,将JSON传递给服务器,但这是一个实验。我知道这在许多层面上都不是最佳的。

表A中包含A型的实体同为表B和C的关系在数据库中的问题是:A有一组B.每一个B的与C.所以配对,如果我用Hibernate和Spring,我可以要求A和服务器将与数组有回应,有含B阵列每一个项目,包含一个艾利C.

我实现

我希望函数'getAObjectDeep'返回一个承诺,当我在承诺上调用成功(回调)时,回调会传递一个类型为A的实体列表,每个实体都包含类型为B的实体数组,而实体类型B又包含类型为C的匹配实体。

这是我写的代码,它不起作用。问题是,当我在第二个promise中调用$ q.all时,类型A的所有实体都会丢失,并且响应中会填充一个B类型实体数组的数组,当我调用$ q.all第三个承诺,类型B的所有实体都会丢失,并且响应中会填入一个'undefined'数组。 我无法控制$ q.all的输出,向下一个承诺传递前一个承诺的值,这个承诺充满了从数据库中获得的新行。

var queryDb = function(query) { 
    return $http.get('/', {params: {sql: query}}); 
}; 

var getAObjectDeep = function(start, end) { 
    return queryDb('SELECT * FROM tableA WHERE tableA.date >= \'' + start + '\' AND tableA.date <= \'' + end + '\' ORDER BY date DESC;') 
    .then(function(response) { 
     return $q.all(_.map(response.data, function(entityA) { 
      return _.extend(entityA, queryDb('SELECT * FROM tableB WHERE idEntityA=' + entityA.id + ';')); 
     })); 
    }) 
    .then(function(response) { 
     return $q.all(_.map(response, function(r) { 
      var entityB = r.data; 
      return _.extend(entityB, queryDb('SELECT * FROM tableC WHERE id=' + entityB.idObjB)); 
     })); 
    }); 
} 
+0

为什么不使用'JOIN'而不是N + 1查询? –

+0

我不认为r。数据存在,因为你已经在前面的代码块中映射了结果r应该是当前的下划线对象 – vbranden

+0

我认为你仍然应该向服务器询问完整的,嵌套的响应 - 较少的流量。不要在客户端生成SQL查询并在服务器上执行它们。你仍然使用与promise和all相同的代码,但是在nodejs中不是角度的。 – Bergi

回答

1

不要忘记,queryDb()将在所有三种情况下返回一个承诺,而且反应是只能通过承诺方式访问,不直接。

第一次使用的queryDb()显示正确的模式:

queryDb(...) 
.then(function() { 
    ... 
}); 

但第二个和第三个使用似乎承担阵列 - 在任何情况下的东西,_.extend()将操作。

据我所知,你需要将两个最内层的表达式“内外”,并且引入一个.then()

var getAObjectDeep = function(start, end) { 
    return queryDb('SELECT * FROM tableA WHERE tableA.date >= \'' + start + '\' AND tableA.date <= \'' + end + '\' ORDER BY date DESC;') 
    .then(function(response) { 
     return $q.all(_.map(response.data, function(entityA) { 
      return queryDb('SELECT * FROM tableB WHERE idEntityA=' + entityA.id + ';').then(function(response2) { 
       return _.extend(entityA, response2); 
      }); 
     })); 
    }) 
    .then(function(response) { 
     return $q.all(_.map(response, function(r) { 
      var entityB = r.data; //??? 
      return queryDb('SELECT * FROM tableC WHERE id=' + entityB.idObjB).then(function(response3) { 
       return _.extend(entityB, response3); 
      }); 
     })); 
    }); 
} 

从异步/承诺的角度来看,原始代码的这种转换使得(更)有意义。

“连接”逻辑与问题中的逻辑相同。没有试图验证它,除非说@ 012b可能不正确,因为@ vbranden指出;如果它不起作用,请尝试var entityB = r