programing

node.js를 사용하여 콜백이 호출될 때까지 함수를 대기시키는 방법

bestcode 2022. 9. 8. 22:18
반응형

node.js를 사용하여 콜백이 호출될 때까지 함수를 대기시키는 방법

다음과 같은 간단한 기능이 있습니다.

function(query) {
  myApi.exec('SomeCommand', function(response) {
    return response;
  });
}

기본적으로 나는 그것이 전화하기를 원한다.myApi.exec콜백 람다에 지정된 응답을 반환합니다.그러나 위의 코드는 작동하지 않고 즉시 반환됩니다.

아주 해킹적인 시도를 하려고 아래를 시도했지만 효과가 없었습니다. 하지만 적어도 당신은 내가 무엇을 달성하려고 하는지 알 수 있습니다.

function(query) {
  var r;
  myApi.exec('SomeCommand', function(response) {
    r = response;
  });
  while (!r) {}
  return r;
}

기본적으로 이 문제를 해결하는 데 적합한 'node.js/이벤트 중심' 방법은 무엇입니까?콜백이 호출될 때까지 함수를 기다렸다가 콜백에 전달된 값을 반환합니다.

이를 위한 "good node.js/event drived" 방법은 기다리지 않는 입니다.

노드 등의 이벤트 구동 시스템을 조작할 때 다른 거의 모든 것과 마찬가지로 함수는 계산 완료 시 호출되는 콜백 파라미터를 받아들여야 합니다.발신자는 통상적인 의미에서 값이 반환되기를 기다리는 것이 아니라 결과 값을 처리하는 루틴을 송신해야 합니다.

function(query, callback) {
  myApi.exec('SomeCommand', function(response) {
    // other stuff here...
    // bla bla..
    callback(response); // this will "return" your value to the original caller
  });
}

따라서 이렇게 사용하지 않습니다.

var returnValue = myFunction(query);

하지만 이렇게.

myFunction(query, function(returnValue) {
  // use the return value here instead of like a regular (non-evented) return value
});

이를 실현하기 위한 한 가지 방법은 API 호출을 약속으로 정리한 후await결과를 기다리다

// Let's say this is the API function with two callbacks,
// one for success and the other for error.
function apiFunction(query, successCallback, errorCallback) {
    if (query == "bad query") {
        errorCallback("problem with the query");
    }
    successCallback("Your query was <" + query + ">");
}

// Next function wraps the above API call into a Promise
// and handles the callbacks with resolve and reject.
function apiFunctionWrapper(query) {
    return new Promise((resolve, reject) => {
        apiFunction(query,(successResponse) => {
            resolve(successResponse);
        }, (errorResponse) => {
            reject(errorResponse);
        });
    });
}

// Now you can use await to get the result from the wrapped api function
// and you can use standard try-catch to handle the errors.
async function businessLogic() {
    try {
        const result = await apiFunctionWrapper("query all users");
        console.log(result);
        
        // the next line will fail
        const result2 = await apiFunctionWrapper("bad query");
    } catch(error) {
        console.error("ERROR:" + error);
    }
}

// Call the main function.
businessLogic();

출력:

Your query was <query all users>
ERROR:problem with the query

https://github.com/luciotato/waitfor-ES6 를 체크해 주세요.

코드를 입력합니다.대상: (오류 생성기, --오류 플래그)

function* (query) {
  var r = yield wait.for( myApi.exec, 'SomeCommand');
  return r;
}

다른 코드를 실행하기 전에 노드에서 콜백 함수가 실행되기를 기다리는 것이 매우 간단하고 쉬운 라이브러리 없이 필요한 경우 다음과 같습니다.

//initialize a global var to control the callback state
var callbackCount = 0;
//call the function that has a callback
someObj.executeCallback(function () {
    callbackCount++;
    runOtherCode();
});
someObj2.executeCallback(function () {
    callbackCount++;
    runOtherCode();
});

//call function that has to wait
continueExec();

function continueExec() {
    //here is the trick, wait until var callbackCount is set number of callback functions
    if (callbackCount < 2) {
        setTimeout(continueExec, 1000);
        return;
    }
    //Finally, do what you need
    doSomeThing();
}

콜백을 사용하지 않을 경우 "Q" 모듈을 사용할 수 있습니다.

예를 들어 다음과 같습니다.

function getdb() {
    var deferred = Q.defer();
    MongoClient.connect(databaseUrl, function(err, db) {
        if (err) {
            console.log("Problem connecting database");
            deferred.reject(new Error(err));
        } else {
            var collection = db.collection("url");
            deferred.resolve(collection);
        }
    });
    return deferred.promise;
}


getdb().then(function(collection) {
   // This function will be called afte getdb() will be executed. 

}).fail(function(err){
    // If Error accrued. 

});

상세한 것에 대하여는, https://github.com/kriskowal/q 를 참조해 주세요.

주의: 이 답변은 프로덕션 코드에 사용되지 않을 수 있습니다.이건 해킹이고 넌 그 의미에 대해 알아야 해.

uvrun 모듈(여기서는 새로운 Nodejs 버전으로 업데이트됨)이 있습니다.이 모듈에서는 libuv 메인이벤트 루프(Nodejs 메인루프)의 단일 루프라운드를 실행할 수 있습니다.

코드는 다음과 같습니다.

function(query) {
  var r;
  myApi.exec('SomeCommand', function(response) {
    r = response;
  });
  var uvrun = require("uvrun");
  while (!r)
    uvrun.runOnce();
  return r;
}

(대체로 사용할 수 있습니다.uvrun.runNoWait()이렇게 하면 블로킹의 문제를 피할 수 있지만 CPU를 100% 사용할 수 있습니다.)

이 접근방식은 Nodej의 목적 전체를 무효화한다는 점에 유의하십시오.즉, 모든 것을 비동기 및 비블로킹으로 합니다.또, 콜 스택의 깊이가 큰폭으로 증가하기 때문에, 스택의 오버플로우가 발생할 가능성이 있습니다.이러한 기능을 재귀적으로 실행하면 반드시 문제가 발생합니다.

코드를 올바르게 재설계하는 방법에 대한 다른 답변을 참조하십시오.

이 솔루션은 테스트를 실시할 때 특히 동기 코드와 시리얼 코드를 필요로 하는 경우에만 도움이 될 수 있습니다.

노드 4.8.0부터 ES6의 제너레이터라는 기능을 사용할 수 있습니다.보다 상세한 컨셉에 대해서는, 이 기사를 참조해 주세요.하지만 기본적으로 발전기와 약속을 사용하여 이 작업을 완료할 수 있습니다.블루버드를 이용해서 발전기를 문란하게 하고 있어요

아래 예시와 같이 코드가 정상이어야 합니다.

const Promise = require('bluebird');

function* getResponse(query) {
  const r = yield new Promise(resolve => myApi.exec('SomeCommand', resolve);
  return r;
}

Promise.coroutine(getResponse)()
  .then(response => console.log(response));

지금은 2020년이고 API는 이미 약속 기반 버전을 가지고 있을 가능성이 높다.단, 일부 인터페이스, 특히 이벤트 이미터에서는 다음 회피책이 필요합니다.

// doesn't wait
let value;
someEventEmitter.once((e) => { value = e.value; });
// waits
let value = await new Promise((resolve) => {
  someEventEmitter.once('event', (e) => { resolve(e.value); });
});

이 경우 다음과 같이 됩니다.

let response = await new Promise((resolve) => {
  myAPI.exec('SomeCommand', (response) => { resolve(response); });
});

Wait는 지난 3년간 새로운 Node.js 릴리즈(v7.6 이후)에 존재해 왔습니다.

기능이 있다고 가정하면:

var fetchPage(page, callback) {
   ....
   request(uri, function (error, response, body) {
        ....
        if (something_good) {
          callback(true, page+1);
        } else {
          callback(false);
        }
        .....
   });


};

다음과 같이 콜백을 사용할 수 있습니다.

fetchPage(1, x = function(next, page) {
if (next) {
    console.log("^^^ CALLBACK -->  fetchPage: " + page);
    fetchPage(page, x);
}
});

비동기식을 사용하여 대기하는 것이 훨씬 더 쉽습니다.

router.post('/login',async (req, res, next) => {
i = await queries.checkUser(req.body);
console.log('i: '+JSON.stringify(i));
});

//User Available Check
async function checkUser(request) {
try {
    let response = await sql.query('select * from login where email = ?', 
    [request.email]);
    return response[0];

    } catch (err) {
    console.log(err);

  }

}

IO의 때 이치:)

node대기시키는 하거나 node.js의 가 에 다른 .r.

강제로 차단해야 하는 경우 아키텍처에 대해 잘못 생각하고 있을 수 있습니다.

언급URL : https://stackoverflow.com/questions/5010288/how-to-make-a-function-wait-until-a-callback-has-been-called-using-node-js

반응형