2016-10-17 2 views
2

나는 this tutorial을 따라 왔고 현재는 작업 연결 풀이있는 MySQL 데이터베이스에 Express js 응용 프로그램을 구축하고 있습니다. 다음 Async.js 내 서버에있는 지침의 폭포에 대한 사용하고 있습니다.비동기 폭포에서 MySQL 연결 풀을 사용하는 ForEach 함수

콜백 지옥을 피하면서 리팩터링하고있었습니다. 중첩 된 ForEach 함수 (콜백 지옥 상황)와 함께 작동하는 코드가있어서 MySql 연결을 완벽하게 얻었 기 때문에 혼란 스럽습니다. 이제는 아무 것도 작동하지 않습니다.

문제 : GET 요청이 수신 에, 그것은 인쇄 "액션 두"와 때까지 그것을 stucks.

이 내 현재 MWE입니다 :

apiRoutes.get('/endpoint', function(req, res) { 
async.waterfall([ 
function actionOne(callback){ 
    connection.acquire(function(err, con){ 
     con.query(myQuery , function(err, result){ 
      con.release(); 
      if(err){ 
       console.log(err); 
       callback(err); 
      } else { 
       console.log("Action One Success"); 
       callback(null, result); 
      } 
     }); 
    }); 
}, 
function actionTwo(list, callback){ 
    console.log("Action Two"); 
    var arr = []; 
    list.forEach(function(item, index, array){ 
     item.arr = []; 
     connection.acquire(function(err, con){ 
      con.query(otherQuery , function(err, result){ 
       con.release(); 
       if(err){ 
        console.log("SQL ERROR: "+err); 
        callback(err); 
       } else { 
        item.arr = result; 
        arr.push(cult); 
        if(index === array.length-1){ 
         console.log("Action Two Success"); 
         callback(null, arr); 
        } 
       } 
      } 
     }); 
    }) 
}, 
function actionThree(item, callback){ 
     .... 
    res.json('success'); 
}],function(err){ 
    if(err) 
     console.log(err); 
}); 

} 




해결했다 마지막으로 내가 Promises를 사용하여 체인 비동기 명령에 가장 적합한 읽을 수있는 솔루션을 찾았습니다. 어떤 이유에 의해, index === array.length-1 사실 적이없는 경우 해당 콜백 함수가 호출되지 않을 것이기 때문에

apiRoutes.get('/endpoint', function(req, res){ 

    //Define 1st function 
    function actionOne(){ 
     return new Promise(function(fulfill, reject){ 
      myAsyncQueryFunction(err, result){ 
       if(err) { reject(err); } 
       else { fulfill(result); } 
      } 
     } 
    }; 

    //Define 2nd function 
    function actionTwo(){ 
     return new Promise(function(fulfill, reject){ 
      actionOne().then(function(result){ 
       my2ndQueryFun(err, result){ 
        if(err) { reject(err); } 
        else { fulfill(result); } 
       } 
      }, reject); 
     } 
    }; 

    //Execute async chained tasks, then send result to client 
    actionTwo().then(function(result){ 
     res.json(result); 
    }; 
} 

답변

1

, 당신의 코드는 actionTwo에 영원히 갇혀있을 것입니다.

또한 쿼리하는 배열의 인덱스를 기반으로 actionTwo 콜백을 호출 할 때 제어하는 ​​것 같습니다. 하지만 그건 실수로 이어질 수 있습니다. connection.acquirecon.query 모두 비동기 적이므로 마지막 색인에있는 것이 리턴 할 마지막 조회임을 보장하지는 않습니다. 목록의 마지막 항목에 대한 쿼리가 가장 빠른 항목 일 경우 어떻게해야합니까? 한 문제는 다음 비동기 방법 connection.acquire이고 con.query :

는 먼저 모든 SQL 쿼리 작업을 선언하고 async.parallel 또는 async.series

function actionTwo(list, callback){ 
    console.log("Action Two"); 


    var tasks = []; 

    list.forEach(function(item, index, array){ 
     item.arr = []; 
     tasks.push(async.apply(getDataFromSQL, item)); 
    }) 

    // could also be async.series(tasks, function (err, results) { 
    // it depends if you want to run the queries in parallel or not 
    async.parallel(tasks, function (err, results) { 
     if (err) { 
      console.log("Action Two Error") 
      return callback(err); 
     } 
     console.log("Action Two Success"); 
     return callback(null, results); //results is an array of the "cult" objects returned at each getDataFromSQL callback 
    }); 


    function getDataFromSQL(item, sqlCallback) { 
     // otherQuery = generate_query_based_on_item(item); 
     connection.acquire(function(err, con){ 
      con.query(otherQuery , function(err, result){ 
       con.release(); 
       if(err){ 
        console.log("SQL ERROR: "+err); 
        sqlCallback(err); 
       } else { 
        item.arr = result; 
        sqlCallback(null, cult); //not sure what cult meant. maybe result? 
       } 
      } 
     }); 
    } 
} 
+0

이 해결 같은 다른 async.js 기능과의 흐름을 제어하는 ​​고려 첫 번째 호출에서는 아무런 문제가 없었지만 두 번째 SQL 결과 이전에 전체 메서드가 반환되기 때문에 두 번째 호출에는 아무런 시간도 없었습니다. 고마워요! –

+0

기타 비동기 기능 사용 참조. 나는 async.waterfall을 사용하기로 결정했다. 왜냐하면 각 함수가 그의 결과를 다음에 전달해야하기 때문이다. 봐 [여기] (http://stackoverflow.com/questions/9258603/what-is-the-difference-between-async-waterfall-and-async-series) –

관련 문제