2017-01-30 1 views
1

최근 웹 응용 프로그램을 개발하여 비동기 속성을 전혀 사용하지 않는다는 것을 알고 있습니다. 그래서 나는 많은 중첩 콜백으로 끝을 맺고있다. 사용자가 특정 API를 통해 서버에서 파일을 얻으려면Node.js 비동기 유스 케이스

예를 들어, 나는

db.query(<select list of permitted files_names>, function(err, filenames) { 
    async.each(file_names, function(name, next) { 
    //open each file to put into array 
    }); 
}) 

이 코드는 파일의 목록을 가져올 데이터베이스를 조회 할 필요가,이 유사한 코드를해야합니다 이름을 비동기 적으로 반복하고 각 파일 내용을 배열에 넣기 전에 마지막으로 완성 된 배열을 클라이언트에 반환합니다.

중첩 된 콜백 및 비동기 라이브러리를 사용하면이 코드는 동기식 코드처럼 작동합니다.

names = db.querySync(//select list of permitted files_names); 
for(name in names) { 
    //open each file to put into array 
} 

동기식 코드를 작성하는 것이 훨씬 낫습니다. 내 유스 케이스가 좀 이상 할 수도 있지만 내 API의 대부분이 비슷한 방식으로 동작하므로 비동기 함수가 필요한 이유가 무엇인지 생각하게한다.

성능면에서이 두 코드의 차이점이 있다면 누군가 가르쳐 주시겠습니까? 이 사용 사례의 성능을 향상시키기 위해 비 차단 속성을 사용하려면 어떻게해야합니까?

+0

검색과 같이 쓸 수있다 위/Aᴍɪʀ @ 자바 스크립트 –

+0

에서 기다리고 - 왜 비동기/await를 관련 것입니까? –

답변

3

비동기 호출을 사용하여 정의하여 사용중인 콜백 함수를 작성하는 경우. 작업이 완료되거나 오류가 발생하면 콜백 함수는 만 실행합니다. 이것들을 사용하기 위해서는 멋진 라이브러리가 필요하지 않습니다. 이것은 노드의 event-loop driven subsystem 작동 방식의 백본입니다.

노드 강하게은 "동기화"호출 사용을 권장하지 않습니다. 노드 코어는 편리함 만이 포함되어 있으며 최후의 수단으로 사용됩니다. 많은 라이브러리는 심지어 비동기 코드 작성에 익숙해 져야하기 때문에 그들을 지원하지도 않습니다. 예를 들어 브라우저 환경에서는 자바 스크립트 런타임을 방해하거나 페이지를 멈추지 않고 차단 호출을 사용할 수 없습니다.

나는 Promises 라인 Bluebird을 사용하여 코드를 규칙적으로 유지하는 것을 선호합니다. 복잡하지 않은 중첩 패턴을 관리하는 데 도움이되는 async 라이브러리와 같은 다른 방법이 있습니다.

몇 가지 특전은 Promise.all 메서드가 완료까지 일련의 약속을 실행 한 다음 다음 단계를 트리거하고, 각 요소에 대해 비동기 코드를 실행 한 다음 목록이 완료 될 때 전진하는 Promise.map을 반복합니다.

코드 정리에 대한 징계를 받으면 그리 나쁘지 않습니다.노드는 Ruby, Python 또는 Java와 같은 전통적인 sync-by-default 언어보다 작업 순서에 더 많은주의를 기울여야하지만, 익숙해 질 수 있습니다. 비동기 코드로 작업하기 시작한 후에는 싸우는 것이 아니라 자주 스레드를 저글링해야하는 다른 언어보다 더 효율적이고 신속하게 작업 할 수 있습니다. 또는 IPC와의 거래.

+0

안녕하세요, 위의 예와 관련하여 비동기 VS 동기화 버전이 동일합니까? 동기 버전에서 동시성이 손실되지 않습니까? 나는 동시성이 많은 요청들 사이의 단일 요청이나 동시성을 언급하는지에 대해 혼동하고있다. – Zanko

+1

동기화 호출을하면 모든 작업이 완료 될 때까지 중단됩니다. 당신의 프로그램이 2-3 초 동안 ** 아무것도하지 않는다는 것을 의미하는 데이타베이스 호출을 위해서. 이것은 프로덕션 코드에서 완전히 받아 들일 수 없습니다. – tadman

+1

프로그램에서 만드는 경향이있는 동기화 호출은 매우 구체적이고 전술적이며, 스크립트의 초기화 단계에서만 발생하므로 정상적인 작동 중에 문제가 발생하지 않습니다.예를 들어, 파일이'require'-로드되기 전에 존재하는지 테스트하거나 디렉토리를 반복하여 올바른 순서로로드합니다. 프로그램이 실행되면 비동기 만 수행됩니다. – tadman

2

이점은 간단합니다 : 비동기 코드를 사용하면 현재 요청 (데이터베이스 쿼리와 같은)이 반환되기 위해 현재 요청이 대기하는 동안 현재 스레드 (Node.js가 단일 스레드라는 것을 기억하십시오)가 다른 요청을 처리 할 수 ​​있습니다 .

대신 동기 코드를 사용하면 대기중인 동안 현재 스레드가 차단되어 그 동안 다른 요청을 처리 할 수 ​​없습니다. 즉, 동시성을 잃게됩니다.


는 약속을 조사, 깨끗한 비동기 코드를 유지 (중첩 콜백을 피하기 위해)하고 ES7 비동기/await를 (모두에서 콜백을 방지하고 단지 동기 코드처럼 보이는 비동기 코드를 작성하기 위해).

+0

안녕하세요, 나는 이것을 정확히 이해하고 있기를 바랍니다. 클라이언트 A가 위와 같은 동기를 수행하고 전체 프로세스가 10 초가 걸리며 클라이언트 B가 동일한 쿼리를 작성하면 클라이언트 B가 클라이언트 A가 완료 될 때까지 기다려야한다고 말하고 있습니까? – Zanko

+1

'ES7 async/await' - node.js에서 아직 지원되지 않으므로 이동해야합니다. –

+1

@ Zanko 웹 프로세스의 인스턴스를 1 개만 실행한다고 가정하면 맞습니다. 그러나 비동기 코드를 사용하면 클라이언트 A가 응답을받을 수 있으며 클라이언트 A는 DB에서 데이터를 반환하기 위해 계속 대기합니다. – Agop

2

예, 성능 측면에서 두 코드의 차이가 있습니다. 동기 코드에서

:

names = db.querySync(//select list of permitted files_names); 

당신이 이름의 목록을 제공하기 위해 여기에 데이터베이스를 요구하고있다. 10 초가 걸린다 고 가정하십시오. 그래서 이번에는 nodeJS가 블로킹 상태로 단일 스레드 된 gos이기 때문입니다. 10 초 후에 나머지 코드가 실행됩니다. for 루프는 5 초가 걸리고 일부 코드는 5 초가 걸리는 것으로 가정합니다.

for(name in names) { 
//open each file to put into array 
} 
//some code 

따라서 총 소요 시간은 20 초입니다.

db.query(<select list of permitted files_names>, function(err, filenames) { 

NodeJs 콜백에 이름의 목록을 제공하기 위해 데이터베이스를 요청합니다 : 비동기 코드 반면

. 10 초가 걸린다 고 가정하십시오. 그리고 즉시 다음 단계 (일부 코드)로 들어가지만 차단 상태가 아닙니다. 일부 코드는 5 초가 걸리는 것으로 가정합니다.

async.each(file_names, function(name, next) { 
//open each file to put into array 
}); 
}) 
//some code. 

5 초 후에 수행 할 I/O 작업이 있는지 확인합니다. 콜백이 반환되면 5 초 동안 (name, next) {..} 함수를 실행합니다.

총 시간은 15 초입니다.

이렇게하면 성능이 향상됩니다.

비동기 코드가 깨끗하고 깨끗해야한다면 클로저를 사용하십시오 & 약속. 예를 들어

는 비동기 코드가 비동기에 대한

fun = function(err, filenames) { 
async.each(file_names, function(name, next) { 
//open each file to put into array 
} 
db.query(<select list of permitted files_names>, fun);