2015-10-24 51 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