수색…


소개

노드는 모든 것이 비동기식으로 실행될 수있는 프로그래밍 언어입니다. 아래에서는 비동기 작업의 몇 가지 예와 일반적인 사항을 확인할 수 있습니다.

통사론

  • doSomething ([args], function ([argsCB]) {/ * 끝났 으면 할 일 * /});
  • doSomething ([args], ([argsCB]) => {/ * 끝났을 때 * /});

콜백 함수

JavaScript의 콜백 함수

콜백 함수는 JavaScript에서 일반적입니다. 함수는 일류 시민 이므로 콜백 함수는 JavaScript에서 가능합니다.

동기 콜백.

콜백 함수는 동기식 또는 비동기식 일 수 있습니다. 비동기 콜백 함수는 동기 콜백 함수의 간단한 예가 더 복잡 할 수 있습니다.

// a function that uses a callback named `cb` as a parameter
function getSyncMessage(cb) {
    cb("Hello World!");
}

console.log("Before getSyncMessage call");
// calling a function and sending in a callback function as an argument.
getSyncMessage(function(message) {
    console.log(message);
});
console.log("After getSyncMessage call");

위 코드의 결과는 다음과 같습니다.

> Before getSyncMessage call
> Hello World!
> After getSyncMessage call

먼저 위 코드가 어떻게 실행되는지 살펴 보겠습니다. 콜백의 개념을 이미 이해하지 못했다면 이미이 단락을 건너 뛰어도된다는 것을 이해한다면 더 이해하기 쉽습니다. 먼저 코드가 파싱 된 다음, Before getSyncMessage call 콘솔에 출력하는 6 행이 Before getSyncMessage call 실행됩니다. 그런 다음 라인 8은 함수 호출하는 실행 getSyncMessage 매개 변수의 이름에 대한 인수로 익명 함수에 전송 cb 에서 getSyncMessage 기능을. 방금 전달 된 함수 cb 를 실행하는 3 행의 getSyncMessage 함수 내에서 실행 getSyncMessage 호출은 전달 된 익명 함수에서 message 라는 param에 인수 문자열 "Hello World"를 보냅니다. 그런 다음 Hello World! 를 기록하는 9 행으로 이동합니다 Hello World! 콘솔에. 그런 다음 실행은 호출 스택 을 종료하는 프로세스를 거치며 ( 또한 참조 ) 10 행 다음 4 행, 마지막으로 11 행으로 이동합니다.

일반적으로 콜백에 대해 알아야 할 정보는 다음과 같습니다.

  • 함수에 콜백으로 보내는 함수는 0 번, 1 번 또는 여러 번 호출 할 수 있습니다. 그것은 모두 구현에 달려 있습니다.
  • 콜백 함수는 동 기적 또는 비동기 적으로 호출 될 수 있으며, 가능하면 동 기적으로 또는 비동기 적으로 호출 될 수 있습니다.
  • 일반 함수와 마찬가지로 함수에 매개 변수를 제공하는 이름은 중요하지 않지만 순서는 같습니다. 예를 들어 8 행에서 매개 변수 message 이름은 statement , msg 또는 jellybean 과 같은 무의미한 message 수 있습니다. 따라서 콜백에 전달되는 매개 변수를 알아야 올바른 이름으로 올바른 순서로 매개 변수를 가져올 수 있습니다.

비동기 콜백.

자바 스크립트에 대해 주목해야 할 것은 기본적으로 동기식이지만 환경 (브라우저, Node.js 등)에 비동기로 설정할 수있는 API가 있습니다 (자세한 내용은 여기에 있습니다 ).

콜백을 허용하는 JavaScript 환경에서 비동기적인 몇 가지 일반적인 사항은 다음과 같습니다.

  • 이벤트
  • setTimeout
  • setInterval
  • 가져 오기 API
  • 약속

또한 위의 함수 중 하나를 사용하는 함수는 콜백을 사용하는 함수로 래핑 될 수 있으며 콜백은 비동기 콜백이됩니다 (콜백을 사용하는 함수로 약속을 래핑하는 것은 약속을 처리하는 더 바람직한 방법이 있습니다).

정보가 주어지면 위의 동기식 함수와 비슷한 비동기 함수를 만들 수 있습니다.

// a function that uses a callback named `cb` as a parameter
function getAsyncMessage(cb) {
    setTimeout(function () { cb("Hello World!") }, 1000);
}

console.log("Before getSyncMessage call");
// calling a function and sending in a callback function as an argument.
getAsyncMessage(function(message) {
    console.log(message);
});
console.log("After getSyncMessage call");

그러면 콘솔에 다음 내용이 출력됩니다.

> Before getSyncMessage call
> After getSyncMessage call
// pauses for 1000 ms with no output
> Hello World!

라인 실행은 "getSyncMessage 호출 전"라인 6 로그로갑니다. 그런 다음 실행은 param cb 대한 콜백을 사용하여 getAsyncMessage를 호출하여 8 행으로 이동합니다. 세 번째 인수로 콜백 및 두 번째 인수로 300을 사용하여 setTimeout을 호출하는 3 행이 실행됩니다. setTimeout 은 콜백에 대해 수행하고 수행하는 작업을 수행하여 나중에 1000 밀리 초 단위로 호출 할 수 있지만 타임 아웃을 설정 한 후 1000 밀리 초를 일시 중지하기 전에 실행을 중단 한 위치로 다시 되돌려 4 행으로 이동합니다 , 11 번째 줄을 멈추고 1 초 동안 멈추고 setTimeout은 그 콜백 함수를 호출합니다.이 콜백 함수는 3 행으로 getAsyncMessages 매개 변수 message 값 "Hello World"가 호출 된 getAsyncMessages 콜백이 9 행의 콘솔에 기록됩니다 .

Node.js의 콜백 함수

NodeJS는 비동기 콜백을 가지고 있으며 일반적으로 errdata 라고하는 두 개의 매개 변수를 함수에 제공 data . 파일 텍스트를 읽는 예제.

const fs = require("fs");

fs.readFile("./test.txt", "utf8", function(err, data) {
    if(err) {
        // handle the error 
    } else {
        // process the file text given with data
    }
});

이것은 한 번 호출되는 콜백의 예입니다.

오류를 처리하는 것은 좋은 방법입니다. 단순히 로깅하거나 던지는 경우에도 마찬가지입니다. throw하거나 반환 할 때 else는 필요하지 않으며 throw 또는 return과 같은 작업을 수행하여 if에서 현재 함수의 실행을 중지하면 들여 쓰기를 줄이기 위해 제거 할 수 있습니다.

그것은 흔히 볼 수 있습니다 있지만 err , data 항상 당신의 콜백이 문서를 보는 것이 가장 좋습니다 그 패턴을 사용하는 경우되지 않을 수 있습니다.

또 다른 예제 콜백은 Express 라이브러리 (express 4.x)에서 제공됩니다.

// this code snippet was on http://expressjs.com/en/4x/api.html
const express = require('express');
const app = express();

// this app.get method takes a url route to watch for and a callback
// to call whenever that route is requested by a user.
app.get('/', function(req, res){
  res.send('hello world');
});

app.listen(3000);

이 예제는 여러 번 호출 된 콜백을 보여줍니다. 콜백은 두 개의 객체로 제공됩니다. 여기서 reqreqres 라는 이름으로 각각 요청과 응답에 해당하며, 들어오는 요청을보고 사용자에게 보낼 응답을 설정할 수있는 방법을 제공합니다.

보시다시피 JavaScript에서 동기화 및 비동기 코드를 실행하는 데 콜백을 사용할 수있는 다양한 방법이 있으며 JavaScript 전체에서 콜백은 매우 유비쿼터스입니다.

코드 예제

질문 : 아래 코드의 출력은 무엇이며 그 이유는 무엇입니까?

setTimeout(function() {
    console.log("A");
}, 1000);

setTimeout(function() {
    console.log("B");
}, 0);

getDataFromDatabase(function(err, data) {
    console.log("C");
    setTimeout(function() {
        console.log("D");
    }, 1000);
});

console.log("E");

출력 : 이것은 잘 알려져 있습니다 : EBAD . C 는 기록 될 때 알 수 없습니다.

설명 : 컴파일러는 setTimeoutgetDataFromDatabase setTimeout 중지되지 않습니다. 그가 기록 할 첫 번째 라인은 E 입니다. 콜백 함수 ( setTimeout 첫 번째 인수) 는 설정된 시간 초과 후 비동기 방식으로 실행됩니다!

자세한 내용은:

  1. E 에는 setTimeout 이 없습니다.
  2. B 의 설정 시간 초과가 0 밀리 초입니다.
  3. A 시간 제한은 1000 밀리 초입니다.
  4. D 그것을해야 후, 데이터베이스를 요청해야합니다 D 는 다음에 오는 있도록 1000 밀리 초를 기다려야 . A
  5. 데이터베이스의 데이터가 요청 될 때 알 수 없으므로 C 는 알 수 없습니다. A 전후 일 수 있습니다.

비동기 오류 처리

잡기를 시도하십시오.

오류는 항상 처리해야합니다. 동기식 프로그래밍을 사용하는 경우 try catch 사용할 수 있습니다. 하지만 비동기로 작업하면이 기능이 작동하지 않습니다! 예:

try {
    setTimeout(function() {
        throw new Error("I'm an uncaught error and will stop the server!");
    }, 100); 
}
catch (ex) {
    console.error("This error will not be work in an asynchronous situation: " + ex);
}

비동기 오류는 콜백 함수 내에서만 처리됩니다!

작동 가능성

v0.8

이벤트 핸들러

Node.JS의 첫 번째 버전에는 이벤트 처리기가 있습니다.

process.on("UncaughtException", function(err, data) { 
    if (err) {
        // error handling
    }
});
v0.8

도메인

도메인 내에서 오류는 이벤트 이미 터를 통해 릴리스됩니다. 이것을 사용함으로써 모든 오류, 타이머, 콜백 메소드가 암시 적으로 도메인 내부에서만 등록됩니다. 오류가 발생하면 오류 이벤트를 보내고 응용 프로그램을 중단시키지 마십시오.

var domain = require("domain");
var d1 = domain.create();
var d2 = domain.create();

d1.run(function() {
    d2.add(setTimeout(function() {
        throw new Error("error on the timer of domain 2");
    }, 0));
});

d1.on("error", function(err) {
    console.log("error at domain 1: " + err);
});

d2.on("error", function(err) {
    console.log("error at domain 2: " + err);
});

콜백 지옥

콜백 함수 안에 콜백 함수를 너무 많이 중첩하면 콜백 지옥 (피라미드 파멸 또는 부메랑 효과)이 발생합니다. 다음은 파일을 읽는 예입니다 (ES6에서).

const fs = require('fs');
let filename = `${__dirname}/myfile.txt`;

fs.exists(filename, exists => {
    if (exists) {
        fs.stat(filename, (err, stats) => {
            if (err) {
                throw err;
            }
            if (stats.isFile()) {
                fs.readFile(filename, null, (err, data) => {
                    if (err) {
                        throw err;
                    }
                    console.log(data);
                });
            }
            else {
                throw new Error("This location contains not a file");
            }
        });
    }
    else {
        throw new Error("404: file not found");
    }
}); 

"콜백 지옥"을 피하는 법

콜백 함수를 두 개 이상 중첩하지 않는 것이 좋습니다. 이렇게하면 코드 가독성을 유지하는 데 도움이되며 앞으로도 유지 관리가 훨씬 쉬워 질 것입니다. 3 개 이상의 콜백을 중첩 할 필요가 있다면 대신 분산 이벤트를 사용하십시오.

또한 async 라고하는 라이브러리가 존재하여 npm에서 콜백 및 해당 실행을 관리 할 수 ​​있습니다. 콜백 코드의 가독성을 높이고 콜백 코드 흐름을 병렬 또는 연속으로 실행할 수 있도록 허용하는 등 콜백 코드 흐름을보다 잘 제어 할 수 있습니다.

원주민 약속

v6.0.0

약속은 비동기 프로그래밍을위한 도구입니다. Javascript의 경우 약속은 그 then 방법으로 알려져 있습니다. 약속에는 두 가지 주 상태 인 '보류 중'과 '정착'이 있습니다. 약속이 '정착'되면 '보류 중'으로 되돌아 갈 수 없습니다. 즉, 약속은 한 번만 발생하는 이벤트에 주로 유용합니다. '정착 된'주에는 '해결 된'과 '거부 된'두 가지 상태가 있습니다. new 키워드를 사용하고 new Promise(function (resolve, reject) {}) 생성자에 함수를 전달하여 새 약속을 만들 수 있습니다.

Promise 생성자에 전달 된 함수는 항상 각각 일반적으로 resolvereject 라는 첫 번째 및 두 번째 매개 변수를받습니다. 이 두 매개 변수의 이름은 관습이지만 약속을 '해결됨'상태 또는 '거부 됨'상태로 설정합니다. 이들 중 어느 하나가 불리면 약속은 '계류 중'에서 '정착'으로 간다. resolve 는 종종 비동기적인 원하는 조치가 수행되고 조치가 오류가 발생하면 reject 가 사용될 때 호출됩니다.

아래의 타임 아웃은 Promise를 반환하는 함수입니다.

function timeout (ms) {
  return new Promise(function (resolve, reject) {
    setTimeout(function () {
      resolve("It was resolved!");
    }, ms)
  });
}

timeout(1000).then(function (dataFromPromise) {
  // logs "It was resolved!"
  console.log(dataFromPromise);
})

console.log("waiting...");

콘솔 출력

waiting...
// << pauses for one second>>
It was resolved!

timeout이 호출되면 Promise 생성자에 전달 된 함수는 지체없이 실행됩니다. 그런 다음 setTimeout 메서드가 실행되고 해당 콜백이 다음 ms 밀리 초 (이 경우 ms=1000 됩니다. setTimeout에 대한 콜백은 아직 시작되지 않았으므로 timeout 함수는 호출 범위에 제어를 반환합니다. then 메소드의 체인은 Promise가 해결되면 나중에 호출되도록 저장됩니다. 여기에 catch 방법이 있다면 그들은 또한 저장 될 것이지만, 약속이 '거부 할 때'/ 때 해고 될 것입니다.

그런 다음 스크립트는 'waiting ...'을 인쇄합니다. 1 초 후 setTimeout은 "It was resolved!"라는 문자열로 resolve 함수를 호출하는 콜백을 호출합니다. 이 문자열은 then 메서드의 콜백으로 전달 된 then 사용자에게 기록됩니다.

같은 의미에서 콜백이 필요한 비동기식 setTimeout 함수를 래핑 할 수 있습니다. 단 하나의 비동기 액션을 약속으로 래핑 할 수 있습니다.

약속에 대한 자세한 내용은 JavaScript 문서 약속을 참조하십시오 .



Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow