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
'programing' 카테고리의 다른 글
벡터 반복, 스캔을 사용한 유형 오류 (0) | 2022.09.15 |
---|---|
DOM 트리 변환 후 Vue.js 구성 요소를 마운트하여 vue 구성 요소를 추가합니다. (0) | 2022.09.15 |
요구 방지필요한 스크립트 캐싱의 JS (0) | 2022.09.08 |
v-on 클릭, 조건이 충족된 경우에만 핸들러 추가 (0) | 2022.09.08 |
빈 테이블 'Primary' 키에 대해 '1' 항목이 중복됩니다. (0) | 2022.09.08 |