개발관련/other

기존 콜백 API를 promises로 변환하는 방법

Rateye 2021. 11. 29. 00:25
728x90
반응형
질문 : 기존 콜백 API를 프라 미스로 어떻게 변환합니까?

약속으로 작업하고 싶지만 다음과 같은 형식의 콜백 API가 있습니다.

1. DOM 로드 또는 기타 일회성 이벤트:

window.onload; // set to callback
...
window.onload = function() {

};

2. 일반 콜백:

 

function request(onChangeHandler) {
    ...
}
request(function() {
    // change happened
    ...
});

3. Node 스타일 콜백("nodeback"):

function getStuff(dat, callback) {
    ...
}
getStuff("dataParam", function(err, data) {
    ...
})

4. node 스타일 콜백이 포함된 전체 라이브러리:

API;
API.one(function(err, data) {
    API.two(function(err, data2) {
        API.three(function(err, data3) {
            ...
        });
    });
});

promises에서 API로 어떻게 작업하고 어떻게 "promisify"할 수 있습니까?

답변

Promise에는 상태가 있으며 보류 중으로 시작하여 다음과 같이 해결할 수 있습니다.

  • 충족 됨은 계산이 성공적으로 완료되었음을 의미합니다.
  • 거부 됨은 계산이 실패했음을 의미합니다.

Promise 반환 함수 는 절대 throw해서는 안되며 대신 거부를 반환해야합니다. promise 반환 함수에서 던지면 } catch { .catch 모두 사용해야합니다. 약속 된 API를 사용하는 사람들은 약속을 기대하지 않습니다. JS에서 비동기 API가 어떻게 작동하는지 확실하지 않은 경우 먼저이 답변을 참조하십시오 .

1. DOM 로드 또는 기타 일회성 이벤트:

.then 생성한다는 것은 일반적으로 정착시기를 지정하는 것을 의미합니다. 즉, 데이터를 사용할 수 있고 .then을 사용하여 액세스 할 수 있음을 나타 내기 위해 이행 또는 거부 단계로 이동할시기를 의미합니다.

네이티브 ES6 promise와 같은 Promise 생성자를 지원하는 최신 Promise 구현 :

function load() {
    return new Promise(function(resolve, reject) {
        window.onload = resolve;
    });
}

그런 다음 결과 약속을 다음과 같이 사용합니다.

load().then(function() {
    // Do things after onload
});

지연을 지원하는 라이브러리 (여기서는이 예제에 $ q를 사용하지만 나중에 jQuery도 사용할 것임) :

function load() {
    var d = $q.defer();
    window.onload = function() { d.resolve(); };
    return d.promise;
}

또는 API와 같은 jQuery를 사용하여 한 번 발생하는 이벤트에 연결 :

function done() {
    var d = $.Deferred();
    $("#myObject").once("click",function() {
        d.resolve();
    });
    return d.promise();
}

2. 일반 콜백:

이러한 API는 자바 스크립트에서 콜백이 일반적이기 때문에 다소 일반적입니다. onSuccessonFail 있는 일반적인 경우를 살펴 보겠습니다.

function getUserData(userId, onLoad, onFail) { …

네이티브 ES6 promise와 같은 Promise 생성자를 지원하는 최신 Promise 구현 :

function getUserDataAsync(userId) {
    return new Promise(function(resolve, reject) {
        getUserData(userId, resolve, reject);
    });
}

지연을 지원하는 라이브러리 사용 (이 예제에서는 jQuery를 사용하지만 위의 $ q도 사용했습니다) :

function getUserDataAsync(userId) {
    var d = $.Deferred();
    getUserData(userId, function(res){ d.resolve(res); }, function(err){ d.reject(err); });
    return d.promise();
}

jQuery는 또한 $.Deferred(fn) 형식을 제공하는데, 다음과 같이 new Promise(fn) 형식을 매우 가깝게 에뮬레이트하는 식을 작성할 수 있다는 장점이 있습니다.

function getUserDataAsync(userId) {
    return $.Deferred(function(dfrd) {
        getUserData(userId, dfrd.resolve, dfrd.reject);
    }).promise();
}

참고 : 여기서 우리는 지연된 jQuery의 resolvereject 메서드가 "분리 가능"하다는 사실을 이용합니다. 즉. jQuery.Deferred () 의 인스턴스 에 바인딩됩니다. 모든 libs가이 기능을 제공하는 것은 아닙니다.

노드 스타일 콜백 (노드 백)에는 콜백이 항상 마지막 인수이고 첫 번째 매개 변수가 오류 인 특정 형식이 있습니다. 먼저 수동으로 약속합시다.

3. Node 스타일 콜백("nodeback"):

getStuff("dataParam", function(err, data) { …
                                                                                                                                                            

에:

function getStuffAsync(param) {
    return new Promise(function(resolve, reject) {
        getStuff(param, function(err, data) {
            if (err !== null) reject(err);
            else resolve(data);
        });
    });
}

지연을 사용하면 다음을 수행 할 수 있습니다 (이 예에서는 Q를 사용하지만 Q는 이제 선호해야하는 새 구문을 지원함).

function getStuffAsync(param) {
    var d = Q.defer();
    getStuff(param, function(err, data) {
        if (err !== null) d.reject(err);
        else d.resolve(data);
    });
    return d.promise;   
}

일반적으로 수동으로 약속을 너무 많이하면 안됩니다. Node 8+의 기본 약속뿐 아니라 Node를 염두에두고 설계된 대부분의 약속 라이브러리에는 노드 백 약속을위한 기본 제공 방법이 있습니다. 예를 들면

var getStuffAsync = Promise.promisify(getStuff); // Bluebird
var getStuffAsync = Q.denodeify(getStuff); // Q
var getStuffAsync = util.promisify(getStuff); // Native promises, node only

4. node 스타일 콜백이 포함된 전체 라이브러리:

여기에는 황금률이 없습니다. 하나씩 약속합니다. 그러나 일부 promise 구현에서는이를 일괄 적으로 수행 할 수 있습니다. 예를 들어 Bluebird에서 nodeback API를 promise API로 변환하는 것은 다음과 같이 간단합니다.

Promise.promisifyAll(API);

또는 Node의 기본 약속 으로 :

const { promisify } = require('util');
const promiseAPI = Object.entries(API).map(([key, v]) => ({key, fn: promisify(v)}))
                         .reduce((o, p) => Object.assign(o, {[p.key]: p.fn}), {});

메모:

  • .then 핸들러에있을 때는 약속 할 필요가 없습니다. .then 반환하면 해당 프라 미스의 값으로 해결되거나 거부됩니다. .then 핸들러에서 던지는 것도 좋은 습관이며 약속을 거부합니다. 이것은 유명한 약속 던지기 안전입니다.
  • 실제에서 onload 경우, 당신은 사용해야 addEventListener 보다는 onX .
출처 : https://stackoverflow.com/questions/22519784/how-do-i-convert-an-existing-callback-api-to-promises
728x90
반응형