Node.js 용 비동기 함수를 작성하는 방법


114

나는 정확히 어떻게 비동기 함수를 작성해야하는지에 대해 연구하려고했습니다. 많은 문서를 훑어 본 후에도 여전히 명확하지 않습니다.

Node 용 비동기 함수를 어떻게 작성합니까? 오류 이벤트 처리를 올바르게 구현하려면 어떻게해야합니까?

내 질문을하는 또 다른 방법은 다음과 같습니다. 다음 기능을 어떻게 해석해야합니까?

var async_function = function(val, callback){
    process.nextTick(function(){
        callback(val);
    });
};

또한 SO ( "node.js에서 비 차단 비동기 함수를 어떻게 생성합니까?") 에서이 질문이 흥미 롭다는 것을 발견했습니다. 아직 답을 얻지 못한 것 같습니다.


14
그것이 내가 묻는 이유입니다. 이러한 기능이 어떻게 다른지 분명하지 않습니다.
Kriem

나는 당신이보고 추천 setTimeout하고 setInterval당신의 마음에 드는 브라우저에서뿐만 아니라 그들과 함께 놀러. 또는 ajax 콜백 (아마 노드 경험에 가장 가까운 것), 또는 클릭 및로드 이벤트와 같이 익숙한 것에 대한 이벤트 리스너. 비동기 모델은 이미 브라우저에 존재하며 노드에서도 똑같습니다.
davin

@davin-그때 비동기 모델을 완전히 이해하지 못하는 것 같아요.
Kriem

@Kriem, 어제 도움이 될만한 답변을했습니다 : stackoverflow.com/questions/6883648/… 귀하의 질문에 대한 답변은 아니지만 주제에 관한 것입니다. 질문을 읽고 거기에 답하고 코드를 가지고 놀면서 무슨 일이 일어나고 있는지 이해하십시오.
davin

2
@Raynos "비동기 함수"의 정의는 무엇입니까?
Anderson Green

답변:


85

비동기 IO와 비동기 함수를 혼동하는 것 같습니다. node.js는 비 차단 IO가 더 낫기 때문에 비동기 비 차단 IO를 사용합니다. 그것을 이해하는 가장 좋은 방법은 Ryan Dahl의 비디오를 보는 것입니다.

Node 용 비동기 함수를 어떻게 작성합니까?

정상적인 함수를 작성하기 만하면됩니다. 유일한 차이점은 바로 실행되지 않고 콜백으로 전달된다는 것입니다.

오류 이벤트 처리를 올바르게 구현하려면 어떻게해야합니까?

일반적으로 API는 첫 번째 인수로 err이있는 콜백을 제공합니다. 예를 들면

database.query('something', function(err, result) {
  if (err) handle(err);
  doSomething(result);
});

일반적인 패턴입니다.

또 다른 일반적인 패턴은 on('error'). 예를 들면

process.on('uncaughtException', function (err) {
  console.log('Caught exception: ' + err);
});

편집하다:

var async_function = function(val, callback){
    process.nextTick(function(){
        callback(val);
    });
};

위의 함수는 다음과 같이 호출 될 때

async_function(42, function(val) {
  console.log(val)
});
console.log(43);

42콘솔에 비동기 적으로 인쇄 합니다. 특히 process.nextTick현재 이벤트 루프 호출 스택이 비어있는 후에 발생합니다. 즉, 호출 스택 후 비어 async_functionconsole.log(43)실행했다. 따라서 43 다음에 42를 인쇄합니다.

이벤트 루프에 대해 읽어야 할 것입니다.


Dahl vids를 봤지만 걱정되는 문제를 이해하지 못하는 것 같습니다. :(
Kriem

1
@Kriem은 업데이트 된 답변을보고 이벤트 루프에 대해
Raynos

1
통찰력을 강화 해 주셔서 감사합니다. 나는 이제 내가 지식이 부족한 것을 더 잘 알고 있습니다. :) 마지막 예가 도움이되었습니다.
Kriem

비동기 IO가 "더 좋다"는 말이 너무 일반적이라고 생각합니다. 이런 의미에서 그렇습니다. 그러나 전반적으로는 그렇지 않을 수 있습니다.
Jake B

첫 번째 코드 예제에서 err 인수를 확인했지만 나중에 반환하지 않았습니다. 오류가 발생하면 코드가 계속되고 잠재적으로 애플리케이션에 심각한 문제가 발생할 수 있습니다.
Gabriel McAdams

9

콜백을 전달하는 것만으로는 충분하지 않습니다. 예를 들어 함수를 비 동기화하려면 settimer를 사용해야합니다.

예 : 비동기 함수가 아닙니다.

function a() {
  var a = 0;    
  for(i=0; i<10000000; i++) {
    a++;
  };
  b();
};

function b() {
  var a = 0;    
  for(i=0; i<10000000; i++) {
    a++;
  };    
  c();
};

function c() {
  for(i=0; i<10000000; i++) {
  };
  console.log("async finished!");
};

a();
console.log("This should be good");

위의 예제를 실행한다면 이것은 좋을 것입니다. 이러한 기능이 작동을 마칠 때까지 기다려야합니다.

의사 다중 스레드 (비동기) 함수 :

function a() {
  setTimeout ( function() {
    var a = 0;  
    for(i=0; i<10000000; i++) {
      a++;
    };
    b();
  }, 0);
};

function b() {
  setTimeout ( function() {
    var a = 0;  
    for(i=0; i<10000000; i++) {
      a++;
    };  
    c();
  }, 0);
};

function c() {
  setTimeout ( function() {
    for(i=0; i<10000000; i++) {
    };
    console.log("async finished!");
  }, 0);
};

a();
console.log("This should be good");

이것은 완전히 비동기 적입니다. 이것은 비동기가 완료되기 전에 작성 될 것입니다.



3

함수가 약속을 반환한다는 것을 알고 있다면 JavaScript에서 새로운 async / await 기능을 사용하는 것이 좋습니다. 구문을 동 기적으로 보이게하지만 비동기 적으로 작동합니다. async함수에 키워드를 추가하면 await해당 범위에서 약속 할 수 있습니다 .

async function ace() {
  var r = await new Promise((resolve, reject) => {
    resolve(true)
  });

  console.log(r); // true
}

함수가 promise를 반환하지 않으면 정의한 새 promise로 래핑 한 다음 원하는 데이터를 해결하는 것이 좋습니다.

function ajax_call(url, method) {
  return new Promise((resolve, reject) => {
    fetch(url, { method })
    .then(resp => resp.json())
    .then(json => { resolve(json); })
  });
}

async function your_function() {
  var json = await ajax_call('www.api-example.com/some_data', 'GET');
  console.log(json); // { status: 200, data: ... }
}

결론 : 약속의 힘을 활용하십시오.


여기서 기억해야 할 것은 약속 본문이 여전히 동 기적으로 실행된다는 것입니다.
shadow0359

2

이것을 시도하면 노드와 브라우저 모두에서 작동합니다.

isNode = (typeof exports !== 'undefined') &&
(typeof module !== 'undefined') &&
(typeof module.exports !== 'undefined') &&
(typeof navigator === 'undefined' || typeof navigator.appName === 'undefined') ? true : false,
asyncIt = (isNode ? function (func) {
  process.nextTick(function () {
    func();
  });
} : function (func) {
  setTimeout(func, 5);
});

18
4 개의 반대표와 하나의 건설적인 의견도 없습니다. : \
Omer

6
@Omer 그런 삶은 SO입니다.
Piece Digital

6
@NorbertoBezi 아마도 코드는 당신에게 자명하지만 답변을 게시 한 사람에게는 아닙니다. 그렇기 때문에 다운 보팅시 설명하는 것이 항상 좋은 습관입니다.
Omer

0

node.js에 대한 그러한 작업에 너무 많은 시간을 처리했습니다. 나는 주로 프론트 엔드 사람입니다.

모든 노드 메서드가 비동기 적으로 콜백을 처리하고이를 Promise로 변환하는 것이 처리하는 것이 더 낫기 때문에 이것이 매우 중요하다고 생각합니다.

나는 가능한 결과를 더 간결하고 읽기 쉽게 보여주고 싶습니다. 비동기로 ECMA-6을 사용하면 다음과 같이 작성할 수 있습니다.

 async function getNameFiles (dirname) {
  return new Promise((resolve, reject) => {
    fs.readdir(dirname, (err, filenames) => {
      err !== (undefined || null) ? reject(err) : resolve(filenames)
    })
  })
}

(undefined || null)위한 REPL 도 미정의 작업을 이용하여 (읽기 이벤트 프린트 루프) 시나리오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.