2015-01-30 7 views
3

이전 클래스에 의존하는 여러 모듈을 인스턴스화하는 클래스를 정의하고 있습니다. 모듈 자체가 준비되기 전에 (즉, mysql 연결을 설정하기 전에) 비동기 작업이 필요할 수 있으므로 일단 모듈이 준비되면 콜백을 호출하여 각 생성자를 제공합니다.자바 스크립트 : 비동기 생성자 패턴

var async = require('async'); 

var child = function(parent, cb) { 
    var self = this; 
    this.ready = false; 

    this.isReady = function() { 
     return self.ready; 
    } 

    /* This does not work, throws error below stating c1.isReady is undefined*/ 
    cb(null, true); 

    /* This works */ 
    setTimeout(function() {  
     self.ready = true; 
     cb(null, true); 
    }, 0); 
} 


var Parent = function(cb) { 
    var self = this; 
    async.series([ 
     function(callback){ 
      self.c1 = new child(self, callback);      
     }, 
     function(callback){ 
      self.c2 = new child(self, callback); 
     } 
    ], 
    function(err, results){ 
     console.log(self.c1.isReady(), self.c2.isReady); 
     console.log(err, results); 
    }); 
} 

var P = new Parent(); 

나는 문제가 생성자 내에서 CB를 호출 같은데요 생성자 완료하기 전에 다음 함수를 비동기 진행을 의미한다 : 즉시 준비 클래스를 인스턴스화 할 때 그러나 나는 문제로 실행했습니다. 이것에 대한 더 나은 접근법이 있습니까? 나는 약속을 사용하는 것을 고려했다. 그러나 나는이 접근법을 이해하기 쉽고 따르기 쉽다고 생각한다.

+0

관련의 종합 정밀 검사의 :의 [? 그것은 생성자 함수는 약속을 반환해야하는 나쁜 관행인가] (http://stackoverflow.com/q/24398699/1048572) – Bergi

+0

가능한 중복 [ 비동기 생성자] (http://stackoverflow.com/questions/11856778/asynchronous-constructor) –

답변

9

콜백의 코드가 아직 본 개체를 참조 할 수 없기 때문에 모든 것이 동기이면 콜백 호출을 지연시켜야합니다. 생성자가 실행을 완료하지 않았기 때문에 반환 값의 할당도 아직 완료되지 않았습니다.

개체를 콜백에 전달하고 해당 참조 (존재하고 완전히 형성됨)를 사용하도록 콜백을 강제 할 수 있지만 일반적으로 허용되는 방식을 사용할 수 없다는 것을 사람들이 알 필요가 있습니다. 콜백이 비동기식으로 만 호출되도록하고 사람들이 정상적인 방법으로 코드를 작성할 수 있도록하는 것이 훨씬 좋습니다.

node.js에서는 목표를 달성하기 위해 대신 setTimeout()을 사용하는 것이 더 효율적입니다. 자세한 내용은 this article을 참조하십시오.

var child = function(parent, cb) { 
    var self = this; 
    this.ready = false; 

    this.isReady = function() { 
     return self.ready; 
    } 

    /* This works */ 
    process.nextTick(function() {  
     self.ready = true; 
     cb(null, true); 
    }, 0); 
} 

여기에 일반적인 관측이다. 많은 사람들 (나 자신을 포함한다)은 이것과 관련된 이유 때문에 생성자에 비동기 연산을 두는 것이 지나치게 복잡하다고 생각합니다. 대신, 자신을 설정하기 위해 비동기 조작을 수행해야하는 대부분의 오브젝트는 .init() 또는 .connect() 메소드 또는 이와 유사한 메소드를 제공합니다. 그런 다음 일반적으로 동기식으로하는 것처럼 객체를 생성 한 다음 초기화의 비동기 부분을 개별적으로 시작하고 콜백을 전달합니다. 그것은이 문제에서 완전히 벗어나게합니다.

비동기 작업 (훌륭한 기능 방향)을 추적하기 위해 약속을 사용하려는 경우 생성자가 객체를 반환하고 약속을 반환하기 위해 .init() 작업을 수행하는 것이 더 쉽습니다. 생성자에서 객체와 약속을 모두 반환하려고 시도하는 것이 지저분 해지고 코드 작성이 더 복잡해집니다.

그런 약속을 사용하여이 작업을 수행 할 수 있습니다

var o = new child(p); 
o.init().then(function() { 
    // object o is fully initialized now 
    // put code in here to use the object 
}, function(err) { 
    // error initializing object o 
}); 
0

당신이 약속에 객체를 넣어 객체로 약속을 넣을 수없는 경우.

약속 속성을 제공하십시오.

위젯의 클래스 계층 구조 (지금은 Typescript에 대해 말하고 있습니다.) 위젯의 기본 클래스는 Ready 속성을 정의하고 이미 해결 된 Promise 객체를 할당 할 수 있습니다. 이렇게이 기본 클래스는 같은 코드를 작성하는 것이 안전 수단이

var foo = Foo(); 
foo.Ready.then(() => { 
    // do stuff that needs foo to be ready 
}); 

파생 된 새로운 약속 개체와 준비의 값을 교체하고, 비동기 코드가 완료 될 때 그것을 해결하여 약속의 해상도를 제어 할 수있는 클래스 .

여기 Asynchronous Constructor design pattern