2013-06-21 4 views
0

기본적으로 json 개체에 대한 데이터를 얻으려면 약 3 호출을해야합니다. 그것은 기본적으로 JSON 개체의 일부 속성을 가진 JSON 배열 중 하나는 두 번째 쿼리를 사용하여 다른 값 배열을 선택하면 그 안에 또 다른 db 호출로 선택된 배열이 있습니다. 노드 js에서 DB 호출의 다양한 문자열을 가장 좋은 방법

나는 .. 나는 아래 전화로 파고와 함께 나는 하나 개의 루트 JSON 객체에 대해 수집 된 모든 정보를 넣어하지만 예기치 않은 동작이 많이 생성의 수 있도록 asyn.concatSeries를 사용하여 JSON의

예 시도

[ 
    { 
     "item" : "firstDbCall" 
     "children" : [ { 
         "name" : "itemDiscoveredWithSecondDBCall" 
         "children" : [ itemsDiscoveredwith3rdDBCall] 
         }, 
        ] 
    } 
] 

이것은 node.js.를 사용하면 실제로 어렵습니다. 나는 이것을 다른 목적을 위해 많은 것을해야하기 때문에 이것을 올바르게하는 법을 정말로 알아야합니다.

수정 이것은 코드입니다. async.concatSeries에는 이상한 동작이 있습니다. 결과는 각 배열에 대해 함수가 완료된 후에 여러 번 호출됩니다. 그래서 나는 수표를 제자리에 두어야했습니다. 나는 그것이 매우 지저분한 코드를 알고 있지만 난 그냥 넣어 봤는데 반창고

console.log("GET USERS HAREDQARE INFO _--__--_-_-_-_-_____"); 
var query = "select driveGroupId from tasks, driveInformation where agentId = '" 
     + req.params.agentId + "' and driveInformation.taskId = tasks.id order by driveInformation.taskId desc;"; 

connection.query(query, function(err, rows) { 
    if (rows === undefined) { 
     res.json([]); 
     return; 
    } 
    if(rows.length<1) { res.send("[]"); return;} 
    var driveGroupId = rows[0].driveGroupId; 
    var physicalQuery = "select * from drives where driveGroupId = " + driveGroupId + ";"; 
    connection.query(physicalQuery, function(err, rows) { 
     console.log("ROWSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS"); 
     console.log(rows); 
     async.concatSeries(rows, function(row, cb) { 
      console.log("-------------------------------SINGLE ROW-------------------------------------"); 
      console.log(row); 
      if(row.hasLogicalDrives != 0) { 
       console.log("HAS LOGICAL DRIVES"); 
       console.log(row.id); 
       var query = "select id, name from logicalDrives where driveId = " + row.id; 
       connection.query(query, function(error, drives) { 
        console.log("QUERY RETURNED"); 
        console.log(drives); 
        parseDriveInfo(row.name, row.searchable, drives, cb); 

       }); 
      } 
      else 
       var driveInfo = { "driveName" : row.name, "searchable" : row.searchable}; 
       console.log("NO SUB ITEMS"); 
       cb(null, driveInfo); 
     }, function(err, results) { 
      console.log("GEETTTTINGHERE"); 
      console.log(results); 
      if(results.length == rows.length) { 
       console.log("RESULTS FOR THE DRIVE SEARCH"); 
       console.log(results); 
       var response = {"id": req.params.agentId}; 
       response.driveList = results; 
       console.log("RESPONSE"); 
       console.log(response); 
       res.json(response); 
      } 
     }); 
    }); 
});  

}; 

parseDriveInfo = function(driveName, searchable, drives, cb) { 
async.concatSeries(drives, function(drive,callback) { 
    console.log("SERIES 2"); 
    console.log(drive); 
    console.log("END OF DRIVE INFO"); 
    var query = "select name from supportedSearchTypes where logicalDriveId = " + drive.id; 
    connection.query(query, function(error, searchTypes) { 
     drive.searchTypes = searchTypes; 
     var driveInfo = { "driveName" :driveName, 
      "searchable" : searchable, 
      "logicalDrives" : drive 
     }; 

     callback(null, driveInfo); 

    }); 
}, function (err, results) { 
    console.log("THIS IS ISISIS ISISISSISISISISISISISISISIS"); 
    console.log(results); 
    if(results.length === drives.length) { 
     console.log("GOTHERE"); 
     cb(null, results); 
    } 
});  

}

+0

당신이 사용하는 라이브러리 및 약간의 코드 샘플에 대한 정보를 제공 할 수 있습니까? – ChrisCM

+0

내가 시도한 코드를 추가했습니다. 도움을 주셔서 감사합니다. –

+0

제가 생각하는 것을 포함하여 답변을 입력했습니다. 다른, 그러나 유사한 시나리오, 그것이 도움이되는지 알려주세요! 그렇지 않으면 내가 파고들 것이다. – ChrisCM

답변

0

편집이 ... 모든 과거 2 시간 그것이 작동되도록하는 것이 이상이 깊이에서 더 많은입니다 당신이 사용하고있는 것처럼 보이는 연결 라이브러리의 사용에 기초한 예제. 참고로,이 중 일부는 javascript psuedo 코드입니다. resultsArray에 객체를 추가하는 것과 같이 명확하게 완료되지 않은 것은 콜백과 관련된 "논리 흐름"입니다. 다른 모든 것들은 당신이 구현할 수있는 것입니다. 동일한 콜백 함수에 대한 여러 호출을 지원하고 호출 간 호출 상태를 유지하려면 가장 좋은 방법은 콜백 집합을 클로저에 래핑하는 것입니다. 이렇게하면 콜백이 기본 이벤트 루프와 일부 상태를 공유 할 수 있습니다. 이것은 ++ 실제로 많은 C에서 클래스 변수처럼, 인자로 전달하지 않고, 콜백에 인수를 전달하거나, 자바 스크립트, 심지어 전역 할 수 있지만, 우리는 전역 범위 :

function queryDataBase(query) { 
//wrap the whole query in a function so the callbacks can share some 
//variables with similar scope. This is called a closure 

    int rowCounter = 0; 
    var dataRowsFromStep2; 
    var resultsArray = {}; 

    connection.query(query, dataBaseQueryStep2); 

    function dataBaseQueryStep2(err, rows) { 
     //do something with err and rows 
     dataRowsFromStep2 = rows; 

     var query = getQueryFromRow(dataRowsFromStep2[rowCounter++]);//Always zero the first time. Might need to double check rows isn't empty! 

     connection.query(query, dataBaseQueryStep3); 
    } 

    function dataBaseQueryStep3(err, rows) { 
     //do something with err and rows 

     if(rowCounter < dataRowsFromStep2.size) { 
      resultsArray.add(rows);//Probably needs to be more interesting, but you get the idea 
      //since this is within the same closure, rowCounter maintains it's state 
      var query = getQueryFromRow(dataRowsFromStep2[rowCounter++]); 

      //recursive call query using dataBaseQueryStep3 as it's callback repeatedly until 
      //we run out of rows to call it on. 
      connection.query(query, dataBaseQueryStep3) 
     } else { 
      //when the if statement fails we have no more rows to run queries on so return to main program flow 
      returnToMainProgramLogic(resultsArray); 
     } 

    } 
} 

function returnToMainProgramLogic(results) { 
    //continue running your program here 
} 

을 poluted하지 않은 나는 개인적으로 위의 논리를 async가 생성하는 문법보다 낫다고 생각한다 ... 문제의 핵심은 async에 대한 중첩 된 호출과 ASYN 자체가 일련의 함수를 비동기 적으로 실행한다는 사실을 믿는다. 알고있다). 이런 식으로 프로그램을 작성하면 걱정할 필요가 없습니다!

+0

그래, 나는 이것들을 알고 있지만 나는 비동기를 사용하여 주변을 돌아 다니고 내가 concat을 사용할 때까지 제대로 작동합니다. 나는 그것을 재구성하려고하고 내가 알아낼 수 있는지 알아 보겠습니다. 감사합니다. –

+0

나는 당신의 코드를 가지고 노는 중이 었으며, 나는 당신의 브래킷에 대해 의심하고 있습니다 ... – ChrisCM

+0

고마워, 고마워! 나는 내가 여기서 논리를 따라갈 수 있다고 생각한다. 비합법적 인 지옥이 훨씬 더 간단하다. –

1

올바른 상황에서 올바른 방법 조합을 사용하려면 async로 충분하면 좋은 경험이 필요합니다. 가장 가능성있는 케이스는 쿼리 1, 쿼리 2 (dataFoundByQuery1), 쿼리 3 (dataFoundByQuery2)의 경우 async.waterfall으로 처리 할 수 ​​있습니다. 그러나 상황에 따라 적절하게 비동기식 메서드를 혼합하고 일치시켜야하며 때로는 2 단계를 거쳐야합니다. 예를 들어 "큰 그림"async.waterfall에서 폭포의 일부 단계는 필요에 따라 async.parallel 또는 async.series을 수행합니다. 나는 async.concat을 사용한 적이 없으며 잘못된 방법을 선택했다고 생각합니다. 대부분의 웹 응용 프로그램은 최소한 & DB 쿼리 사용 사례를 접하기 때문에 async.each, async.eachSeries, async.waterfallasync.map입니다. 따라서 좀 더 구체적인 방법을 알아보기 전에 이해할 수 있도록하십시오.

+0

나는 폭포와 물건에 문제가 있다는 것을 안다. 정확한 숫자는 모른다. 결과는 내가 얻을 것이다, 그래서 내가 실행 해야하는 기능의 동적 번호가 ... concat 처리하기 때문에 나는 단지 그것을 여러 번 호출하는 값의 배열을 제공하기 때문에 .. 내가 할 수있는 방법이 있나요 async.series 불확정 한 길이의 함수 배열? –

+0

또한 나는 async.eachSeries를 사용할 수 없다. 왜냐하면 그것은 최종 결과에 어떤 데이터도 전달하지 않기 때문이다. 나는 모든 데이터를 수집 한 후에 보내기 위해 json 객체에 넣을 필요가 있기 때문에 데이터를 전달해야한다. 요청자에게 다시 .. 여기 뭔가가 빠졌나요? –

+0

FUNCTIONS의 길이가 일정하지 않으므로 INVOCATIONS 길이가 불확실합니다. concat 및 series (및 첫 번째 인수로 배열을 사용하는 함수)는 임의의 길이의 배열을 처리합니다. 결과의 정확한 수를 알 필요는 없습니다. 비동기 및 몇 가지 실험 및 자습서로 더 많은 시간을 할애해야한다고 생각합니다. 그것은 당신이 필요로하는 것을 할 수 있지만 순간에 당신은 구체적인 대답이 아닌 튜토리얼이 필요합니다. –

0

강력히 권하고 싶습니다. sequelize.js 이것은 정말 쿼리를 체인화 할 수있는 강력한 기능을 제공합니다.또한 js 객체에 데이터를 직접로드하고 동적 SQL을 작성하며 다양한 데이터베이스에 연결할 수 있습니다. Node를위한 Ruby 세계의 그림 ActiveRecord.