2016-08-14 3 views
4

나는 아주 기본적인 예제 코드부터 시작하기 때문에 ES6 표준을 배우고 있습니다.ES6에서 콜백 코드를 약속하는 방법

JavaScript에 콜백 hells이 있으므로 콜백 사용을 피하고 싶습니다. 하지만 콜백 스타일 코드를 약속으로 변환하는 방법을 모르는 문제를 만났습니다. 나는 그런 코드가있는 경우 예를 들어

module.exports = (x, y, callback) => { 
    try { 
    if (x < 0 || y < 0) { 
     throw new Error('Rectangle dimensions are wrong.'); 
    } else { 
     callback(null, { 
     perimeter() { 
      return (2 * (x + y)); 
     }, 
     area() { 
      return (x * y); 
     }, 
     }); 
    } 
    } catch (error) { 
    callback(error, null); 
    } 
}; 

가 어떻게 그것을 ES6의 Promise로 변환해야합니다 아래처럼 보인다? 콜백을 약속으로 변환하는 것이 권장되는 행동입니까?

이 예제를 읽었지만 결과는 사실 혼란 스러웠습니다. 콜백을 약속으로 다시 작성하기 전에 먼저 이것을 이해해야한다고 생각합니다.

let promise = new Promise(function(resolve, reject) { 
    console.log('Promise'); 
    resolve(); 
}); 

promise.then(function() { 
    console.log('Resolved.'); 
}); 

console.log('Hi!'); 

// Promise 
// Hi! 
// Resolved 

제 생각에 Promise은 생성 직후 실행됩니다. 그러나 나는 then 메서드의 코드가 마지막으로 실행되는 이유를 알지 못합니다.

+1

Promise/A + [here] (https://promisesaplus.com/)의 사양을 읽으면 2.2.4 및 관련 참고 3.1에 특히주의하십시오. 기본적으로'.then' 콜백은 비동기입니다. –

답변

2

기존 답변은 deferred anti-pattern에 속합니다. 불필요하게 자세한 것이므로 전체 Promise API를 활용하지 않으므로이 접근법을 피할 것입니다. 또 다른 대답은 약속을 사용합니다. 실제로 타사 스크립트를 사용하여 콜백 스타일을 사용하여 작성된 코드를 변경할 수없는 경우 promisification을 사용해야 만합니다.

두 번째 질문은 두 번째 질문입니다. 약속은 귀하가 주어진 예에서 본 것과 같은 방식으로 행동하는 이유입니다. 이 질문에 대한 답을 찾으려면이 성격의 많은 기존 질문을 사용하는 것이 좋습니다. 함수가 비동기의 완료에 의존하지 자체 않기 때문에

module.exports = (x, y) => { 
    if (x < 0 || y < 0) { 
    return Promise.reject(new Error('Rectangle dimensions are wrong.')); 
    } else { 
    return Promise.resolve({ 
     perimeter() { 
     return (2 * (x + y)); 
     }, 
     area() { 
     return (x * y); 
     }, 
    }); 
    } 
}; 

// e.g. success 
createRectangle(10, 10) 
    .then(rect => { 
    console.log(rect.area()) //=> 100 
    }) 

// e.g. failure 
createRectangle(-1, -1) 
    .catch(err => { 
    console.log(err) //=> "Error: Rectangle dimensions are wrong." 
    }) 

예를 들어, 약속을 사용하도록 코드를 리팩토링하는 방법의 첫 번째 질문에 관해서는 aren't Promises just callbacks?

, 여기에 내 제안이다 작업 도우미 메서드 Promise#resolvePromise#reject을 사용하여 "사각형"개체 만들기의 성공 또는 실패를 나타내는 함수에서 Promise를 반환 할 수 있습니다. 이것들은 각각 상태이 값으로 또는 오류로 해결되거나 거부되는 새로운 Promise를 생성합니다.

+0

Cool 이게 내가 원하는거야. Promise에 대한 다른 게시물을 확인해 보겠습니다. – Kulbear

0
module.exports = (x, y, callback) => { 
    new Promise(function(resolve, reject) { 
    if (x < 0 || y < 0) reject(new Error('Rectangle dimensions are wrong.')) 
    else resolve({ 
     perimeter() { 
     return (2 * (x + y)); 
     }, 
     area() { 
     return (x * y); 
     } 
    }) 
    }) 
    .then(callback) 
    .catch(callback) 
} 

".then"를 기억하고 ".catch"는 비동기입니다.

-1

약속이 정말 좋아하지만, 처음에, 약간 혼동이 될 수이 코드를 확인하십시오 당신이 당신의 모듈을 호출 할 때 내 예에서

module.exports = (x, y) => { 
var deferred = q.defer();// this will be our promise 
    try { 
    if (x < 0 || y < 0) { 
     //return an error to be catched by catch method 
     deferred.reject(new Error('Rectangle dimensions are wrong.')); 
    } else { 
     //return the event to the next function with this value 
     deferred.resolve({ 
     perimeter() { 
      return (2 * (x + y)); 
     }, 
     area() { 
      return (x * y); 
     }, 
     }); 
    } 
    } catch (error) { 
    deferred.reject(error); 
    } 

return deferred.promise; //Here return the promise 
}; 

//You will use it like this 
module(x,y) 
.then(callback) 
.then(function(data){ 
}) 
.catch(function(error){ 
}); 

을, 당신은 바로 약속을 얻을 수 있지만, 코드가됩니다 코드가 실행 된 후 "then"메소드에서 이벤트를 받거나 catch에서 어떤 일이 발생하면 이벤트가 발생합니다.

저는 q 라이브러리가 약속을 처리하는 것을 좋아합니다. 오류가 발생하면 오류를 반환하고 체인을 중지하는 방법에 대해 많은 권한을 부여합니다. 기본적으로 함수의 흐름을보다 잘 제어 할 수 있습니다.

희망 하시겠습니까?

0

이것은 중요한 주제입니다. 동기식 방식으로 기능 코딩을하기 위해서는 약속을 사용하는 시점은 callback의 로직을 then 단계로 이동시키는 것입니다. 그래서 당신은 약속 자체 내에서 논리를 다루지 않아도되지만 then 단계에서 논리를 처리해서는 안됩니다. 이 사고 방식은 모든 특정 유형 콜백 구조에 대해 작동하는 범용 promisify 유틸리티 함수를 만드는 데 도움이됩니다. 귀하의 경우 콜백 유형은 노드 표준 오류 첫 번째 유형입니다. 따라서 아래의 코드에 따라

module.exports = (x, y, callback) => { 
    try { 
    if (x < 0 || y < 0) { 
     throw new Error('Rectangle dimensions are wrong.'); 
    } else { 
     callback(null, { 
     perimeter() { 
      return (2 * (x + y)); 
     }, 
     area() { 
      return (x * y); 
     }, 
     }); 
    } 
    } catch (error) { 
    callback(error, null); 
    } 
}; 

일반적인 promisfy 함수는 다음과 같이 작동해야합니다.

var moduleExports = (x, y, callback) => { 
 
    try { 
 
    if (x < 0 || y < 0) { 
 
     throw new Error('Rectangle dimensions are wrong.'); 
 
    } else { 
 
     callback(null, { 
 
     perimeter() { 
 
      return (2 * (x + y)); 
 
     }, 
 
     area() { 
 
      return (x * y); 
 
     }, 
 
     }); 
 
    } 
 
    } catch (error) { 
 
    callback(error, null); 
 
    } 
 
}; 
 

 
function promisfy(fun, ...args){ 
 
    return new Promise((v,x) => fun(...args, (err,data) => !!err ? x(err) : v(data))); 
 
} 
 

 
var p = promisfy(moduleExports,4,5); 
 
p.then(val => console.log(val,val.area(),val.perimeter()), err => console.log(err)); 
 

 
// p.then(val => callback(null,val), err => callback(err))
그래서 당신은 값 인수로 then 단계 onFulfillment에 공급되는 areaperimeter 기능을 사용하여 결과 개체가이 특별한 경우이다. 따라서 로직을 호출하여 onFulfillment 함수 ( then 첫 번째 콜백 단계)에서 처리하고 onReject 함수 ( then 두 번째 콜백)의 오류를 처리해야합니다.마지막 줄에 위의 스 니펫에 주석으로 표시합니다.

PS : 나는 vresolvex (명백한)이 약속의 reject 콜백을 지정하는 지정 (체크 모양)를 사용합니다.

관련 문제