code

콜백이 돌아올 때까지 "기다리는" 방법은?

starcafe 2023. 9. 20. 20:38
반응형

콜백이 돌아올 때까지 "기다리는" 방법은?

아래 예와 같이 간단한 콜백을 사용하는 경우:

test() {
  api.on( 'someEvent', function( response ) {
    return response;
  });
}

비동기식 / wait를 사용하도록 기능을 변경하려면 어떻게 해야 합니까?구체적으로 'someEvent'가 한 번, 한 번만 호출이 보장된다고 가정할 때, 다음과 같이 콜백이 실행될 때까지 함수 테스트가 반환되지 않는 비동기 함수이면 좋겠습니다.

async test() {
  return await api.on( 'someEvent' );
}

async/await마법이 아닙니다.비동기 기능은 당신을 위한 약속을 풀 수 있는 기능이므로 당신은 다음이 필요할 것입니다.api.on()약속을 이행할 수 있게 해주는 거죠이와 같은 것:

function apiOn(event) {
  return new Promise(resolve => {
    api.on(event, response => resolve(response));
  });
}

그리고나서

async function test() {
  return await apiOn( 'someEvent' ); // await is actually optional here
                                      // you'd return a Promise either way.
}

하지만 이 또한 거짓말입니다. 왜냐하면 비동기 기능은 약속 자체를 반환하므로 실제로 가치를 얻을 수 없기 때문입니다.test(), 대신 다음과 같이 사용할 수 있는 가치에 대한 약속(Promise for a value.

async function whatever() {
  // snip
  const response = await test();
  // use response here
  // snip
}

간단한 해결책이 없다는 것이 짜증나고, 포장.return new Promise(...)도망치긴 하지만, 그를 이용한 적절한 해결책을 찾았습니다.util.promisify(actually 역시 같은 포장을 하고, 더 보기 좋아 보입니다.)

function voidFunction(someArgs, callback) {
  api.onActionwhichTakesTime(someMoreArgs, (response_we_need) => {
    callback(null, response_we_need);
  });
}

위 기능은 아직 아무것도 반환하지 않습니다.우리는 그것을 돌려줄 수 있습니다.Promiseresponse전해진callback다음을 수행하여

const util = require('util');

const asyncFunction = util.promisify(voidFunction);

이제 우리는 실제로 할 수 있습니다.awaitcallback.

async function test() {
  return await asyncFunction(args);
}

사용할 때 몇 가지 규칙util.promisify

  • callback앞으로 일어날 함수의 마지막 논쟁임에 틀림없습니다.promisify
  • 콜백 추정치는 다음과 같은 형식이어야 합니다.(err, res) => {...}

재미있는 것은 우리가 무엇이 무엇인지를 구체적으로 쓸 필요가 없다는 것입니다.callback사실은 그렇습니다.

비동기/await은 마법입니다.함수를 만들 수 있습니다.asPromise이런 상황에 대처하는 방법:

function asPromise(context, callbackFunction, ...args) {
    return new Promise((resolve, reject) => {
        args.push((err, data) => {
            if (err) {
                reject(err);
            } else {
                resolve(data);
            }
        });
        if (context) {
            callbackFunction.call(context, ...args);
        } else {
            callbackFunction(...args);
        }
    });
}

필요할 때 사용할 수 있습니다.

async test() {
    return await this.asPromise(this, api.on, 'someEvent');
}

arg의 수는 가변적입니다.

const getprice = async () => {
return await new Promise((resolve, reject) => {
    binance.prices('NEOUSDT', (error, ticker) => {
        if (error) {
            reject(error)
        } else {
            resolve(ticker);
        }
    });
})}

router.get('/binanceapi/price', async function (req, res, next) {
res.send(await binanceAPI.getprice());});

콜백 없이도 이를 달성할 수 있습니다. 여기서는 콜백 대신 약속 비동기를 사용하는 방법을 사용합니다.그리고 여기서는 오류를 처리하는 두 가지 방법을 설명했습니다.

clickMe = async (value) => {
  
  // begin to wait till the message gets here;
  let {message, error} = await getMessage(value);
  
  // if error is not null
  if(error)
    return console.log('error occured ' + error);
   
  return console.log('message ' + message);

}

getMessage = (value) => {

  //returning a promise 
  return new Promise((resolve, reject) => {
  
    setTimeout(() => {
      // if passed value is 1 then it is a success
      if(value == 1){
        resolve({message: "**success**", error: null});
      }else if (value == 2){
        resolve({message: null, error: "**error**"});
      }
    }, 1000);
  
  });

}

clickWithTryCatch = async (value) => {

  try{
    //since promise reject in getMessage2 
    let message = await getMessage2(value);
    console.log('message is ' + message);
  }catch(e){
    //catching rejects from the promise
    console.log('error captured ' + e);
  }

}

getMessage2 = (value) => {

  return new Promise((resolve, reject) => {
  
    setTimeout(() => {
      if(value == 1)
        resolve('**success**');
      else if(value == 2)
        reject('**error**'); 
    }, 1000);
  
  });

}
<input type='button' value='click to trigger for a value' onclick='clickMe(1)' />
<br/>
<input type='button' value='click to trigger an error' onclick='clickMe(2)' />
<br/>
<input type='button' value='handling errors with try catch' onclick='clickWithTryCatch(1)'/>
<br/>
<input type='button' value='handling errors with try catch' onclick='clickWithTryCatch(2)'/>

반환 약속 함수를 정의합니다.

export const callbackf = (f, ...args) => new Promise((resolve, reject) => {
    f(...args, (error, data) => {
        if (error) {
            reject(error);
        } else {
            resolve(data);
        }
    });
});

필요한 곳에서 약속을 기다립니다. arg1, arg2, ...는 콜백 함수 인수입니다.

await callbackf(yourCallbackFunction, arg1, arg2, arg3, argN)

언급URL : https://stackoverflow.com/questions/37104199/how-to-await-for-a-callback-to-return

반응형