[node.js] 콜백을 기다리는 동안 Node.js가 종료되는 것을 방지하는 방법은 무엇입니까?

다음과 같은 코드가 있습니다.

var client = new mysql.Client(options);
console.log('Icanhasclient');

client.connect(function (err) {
  console.log('jannn');
  active_db = client;
  console.log(err);
  console.log('hest');

  if (callback) {
    if (err) {
      callback(err, null);
    }

    callback(null, active_db);
  }
});

내 문제는 노드를 실행하면 즉시 종료된다는 것입니다. ‘Icanhasclient’를 인쇄하지만 콜백 내부의 console.log는 호출되지 않습니다.

(이 예에서 mysql은 node-mysql 입니다.

종료하기 전에 node.js가 콜백이 완료되기를 기다리도록 할 수있는 작업이 있습니까?



답변

콜백이 대기되지 않음

모든 이벤트 가 비워 질 때까지 노드가 실행됩니다 . 다음 과 같은 호출이 발생하면 콜백이 이벤트 대기열에 추가 됩니다.

  emmiter1.on('this_event',callback).

실행되었습니다. 이 호출은 모듈 개발자가 작성한 코드의 일부입니다.

모듈이 동기 / 차단 버전의 빠른 포트 인 경우 작업의 일부가 완료 될 때까지 발생하지 않을 수 있으며 모든 대기열이 발생하기 전에 비워져 노드가 조용히 종료 될 수 있습니다.

이는 모듈 개발자가 개발 중에 발생하지 않을 수있는 교활한 버그입니다 . 이는 중요한 시간에 모든 대기열 이 비어있는 경우가 드물기 때문에 대기열 이 많은 바쁜 시스템에서는 덜 자주 발생 하기 때문입니다.

사용자를위한 가능한 수정 / 버그 감지기는 의심되는 함수 호출 전에 특수 타이머 이벤트를 삽입하는 것입니다.


답변

setInterval을 사용하여 setTimeout 또는 반복 제한 시간을 발행 할 수 있습니다.

종료 조건을 확인하려면 조건부 제한 시간을 수행 할 수도 있습니다.

(function wait () {
   if (!SOME_EXIT_CONDITION) setTimeout(wait, 1000);
})();

이것을 코드의 끝에 넣으면 콘솔은 당신이 닫고 싶을 때까지 기다릴 것입니다.


답변

내 솔루션은 EventEmitter를 인스턴스화하고 내 사용자 지정 이벤트를 수신하는 것이 었습니다.

var eventEmitter = new process.EventEmitter();

그런 다음 eventEmitter.emit비동기 콜백에서 호출했습니다.

client.connect(function (err) {
    eventEmitter.emit('myevent', {something: "Bla"})
});

내 스크립트의 마지막 것은 다음과 eventEmitter.on같습니다.

eventEmitter.on('myevent', function(myResult){
  // I needed the result to be written to stdout so that the calling process could get it
  process.stdout.write(JSON.stringify(myResult));
});

그러면 노드는 이벤트 핸들러가 실행을 마칠 때까지 기다립니다.


답변

@Todd의 답변을 바탕으로 한 줄짜리를 만들었습니다. 스크립트 시작 부분에 포함하고 done = true완료되면 설정하십시오 .

var done = (function wait () { if (!done) setTimeout(wait, 1000) })();

예:

var done = (function wait () { if (!done) setTimeout(wait, 1000) })();

someAsyncOperation().then(() => {
  console.log('Good to go!');
  done = true;
});

어떻게 작동합니까? 조금 확장하면 :

// Initialize the variable `done` to `undefined`
// Create the function wait, which is available inside itself
// Note: `var` is hoisted but `let` is not so we need to use `var`
var done = (function wait () {

  // As long as it's nor marked as done, create a new event+queue
  if (!done) setTimeout(wait, 1000);

  // No return value; done will resolve to false (undefined)
})();


답변

여기 내 두 센트가 있습니다.

async function main()
{
    await new Promise(function () {});
    console.log('This text will never be printed');
}

function panic(error)
{
    console.error(error);
    process.exit(1);
}

// https://stackoverflow.com/a/46916601/1478566
main().catch(panic).finally(clearInterval.bind(null, setInterval(a=>a, 1E9)));


답변

방법은 다음과 같습니다. 주 진입 점이 약속을 반환하도록 한 다음이 작은 래퍼를 사용하여 약속이 해결되지 않는 한 노드가 종료되지 않도록합니다.

function wrapPromiseMain(entryPoint) {
    const pollTime = 1000000;
    let interval = setInterval(() => {}, pollTime);

    return entryPoint().finally(() => {clearInterval(interval)});
}

이를 사용하려면 기본 진입 점을 약속하고 래퍼에 인수로 전달하면됩니다.

function main() {

    // ... main stuff ...

    return doSomethingAsync();
}

wrapPromiseMain(main);

약속이 정해지면 타이머를 자동 취소하므로 추가 지연 시간을 추가하지 않기 때문에 기본 폴링 루프보다 약간 더 깔끔합니다. 따라서 원하는 경우 폴링 시간은 기본적으로 영구적 일 수 있습니다.


답변

felixge / node-mysql 라이브러리를 살펴 보았지만 API에서 client.connect 명령에 대한 참조를 보지 못했습니다. 이것이 당신이하려는 실제 전화입니까 (여기서는 까다 롭지 않음)? 그럼에도 불구하고 IMHO는 대부분의 다른 인기있는 언어와 다른 프로그래밍 패러다임을 사용하기 때문에 Javascript가 어떻게 디자인되었는지에 대해 더 많이 생각할 필요가 있습니다.

코드에서 내가 보는 첫 번째 문제는 콜백을 정의하지 않았으므로 실제로 존재하지 않는다는 것입니다. console.log (callback)이 정의되지 않았다고 가정합니다. 코드에서 익명 함수는 client.connect 함수의 ‘콜백’입니다. 더 높은 범위에서 ‘콜백’이라고 부르는 것을 정의해야합니다. 예를 들어 myCallback 함수를 client.connect의 익명 함수보다 높은 범위에 존재하도록 정의합니다. Javacscript 변수 범위 를 조회하는 것이 유용 할 수 있습니다 .

    var myCallback(err, response) {
      if (err) {
        console.log('err:%s',err);
      } else {
        console.log('response:%s',response);
      }
    }

    client.connect(err, function(response) {
      // this anonymous function is the callback to client.connect, the var
      // 'callback' would be undefined.
      if (err) {
        myCallback(err);
        return; // Explicit call to return, else the lines below would run.
      }
      myCallback(null, response);
    });

둘째, Javascript 내에서 명시 적으로 return을 호출하지 않으면 함수가 계속 처리됩니다. 나는이 물린했다 나 자신 . 마지막으로 Javascript는 이벤트 구동 루프를 실행하므로 함수가 값을 반환 할 때까지 기다리지 않습니다. 이것이 우리가 처음에 이러한 모든 콜백을 갖는 이유입니다. 예를 들어 조건이 참이 될 때까지 while 루프를 사용하여 Javascript가 다르게 작동하도록 할 수 있습니다. 이벤트 루프를 조작하는 다양한 전략은 caolan 의 ‘async’라이브러리를 참조하십시오 . 이러한 메서드를 남용 할 때의 가장 큰 단점은 더 많은 콜백을 사용해야 할 때 실제로 CPU주기 / 차단을 낭비하고 프로그램 작동 방식을 다시 생각해야한다는 것입니다.