복붙노트

[NODEJS] 이 생성자 함수는 약속을 반환해야하는 나쁜 관행인가?

NODEJS

이 생성자 함수는 약속을 반환해야하는 나쁜 관행인가?

해결법


  1. 1.예, 그것은 나쁜 방법입니다. 생성자는 다른 동급, 아무것도의 인스턴스를 반환해야합니다. 그것은 혼란 그렇지 않으면 새로운 연산자와 상속 UP 것.

    예, 그것은 나쁜 방법입니다. 생성자는 다른 동급, 아무것도의 인스턴스를 반환해야합니다. 그것은 혼란 그렇지 않으면 새로운 연산자와 상속 UP 것.

    또한, 생성자는 생성하고 새로운 인스턴스를 초기화합니다. 이 데이터 구조 및 모든 인스턴스 별 속성을 설정하지만, 어떤 작업을 실행하지 않아야합니다. 그것은이 모든 혜택과 부작용 가능한 경우가없는 순수한 기능을해야합니다.

    그게 당신의 클래스의 방법에 가야한다. 당신은 전역 상태를 돌연변이 싶어? 이어서없는 오브젝트를 생성하는 부작용으로, 명시 적 프로 시저를 호출한다. 이 호출은 인스턴스 직후에 갈 수 있습니다 :

    var engine = new Engine()
    engine.displayPosts();
    

    해당 작업이 비동기 경우, 당신은 지금 쉽게 완료 될 때까지 쉽게 기다려야하는, 방법에서 그 결과에 대한 약속을 반환 할 수 있습니다. 이 방법은 (비동기) 돌연변이 인스턴스와 다른 방법이에 따라 달라 때이 그들을 기다린다 (실제로 동기 경우에도 비동기가) 필요되는 이어질 것으로 나는 그러나,이 패턴을 권하고 싶지 않다 당신은 신속하게이 것 일부 내부 큐 관리는 계속. 코드 인스턴스는 존재하지만 실제로 사용할 수 없게하지 마십시오.

    자신에게 물어 : 당신은 실제로 데이터없이 인스턴스가 필요하십니까? 당신은 어떻게 든 사용할 수 있을까요?

    그 대답이 없음을 경우 당신이 데이터를하기 전에, 당신은 그것을 만들 것이다. 대신 데이터를 가져하는 방법 생성자를 말하는 (또는 데이터에 대한 약속을 전달)의, 생성자에 데이터 ifself 매개 변수를 확인합니다.

    그런 다음 약속을 반환되는 데이터를로드하는 정적 메소드를 사용합니다. 그런 다음에 새로운 인스턴스의 데이터를 래핑 전화 체인 :

    Engine.load({path: '/path/to/posts'}).then(function(posts) {
        new Engine(posts).displayPosts();
    });
    

    이 데이터를 취득 할 수있는 방법으로 훨씬 더 큰 유연성을 허용하고, 생성자에게 많은 단순화합니다. 마찬가지로, 정적 공장 기능을 작성할 수 있습니다 그 엔진 인스턴스에 대한 반환 약속 :

    Engine.fromPosts = function(options) {
        return ajax(options.path).then(Engine.parsePosts).then(function(posts) {
            return new Engine(posts, options);
        });
    };
    
    …
    
    Engine.fromPosts({path: '/path/to/posts'}).then(function(engine) {
        engine.registerWith(framework).then(function(framePage) {
            engine.showPostsOn(framePage);
        });
    });
    

  2. 2.저도 같은 문제가 발생하여이 간단한 해결책을했다.

    저도 같은 문제가 발생하여이 간단한 해결책을했다.

    대신 생성자에서 약속을 반환하는이 같은 this.initialization 속성에 넣어 :

    function Engine(path) {
      var engine = this
      engine.initialization = Promise.resolve()
        .then(function () {
          return doSomethingAsync(path)
        })
        .then(function (result) {
          engine.resultOfAsyncOp = result
        })
    }
    

    그런 다음, 그와 같이 초기화 후 실행되는 콜백의 모든 방법을 포장 :

    Engine.prototype.showPostsOnPage = function () {
      return this.initialization.then(function () {
        // actual body of the method
      })
    }
    

    어떻게이 API 소비자의 관점에서 본다 :

    engine = new Engine({path: '/path/to/posts'})
    engine.showPostsOnPage()
    

    이미 해결 않다면 콜백을 부착 할 때, 당신은 약속을 여러 콜백을 등록 할 수 있습니다 그것을 해결 한 후 그들 중 하나를 실행하거나 때문에이 작동합니다.

    작품을 mongoskin 어떻게 실제로 약속을 사용하지 않는 것을 제외이다.

    편집 : 그것을 사용하는 또 다른 예는이 그래서 내가 ES6 / 7 구문과 사랑에 나는 빠졌어 그 답장을 썼다 때문에. 당신은 바벨 오늘 사용할 수 있습니다.

    class Engine {
    
      constructor(path) {
        this._initialized = this._initialize()
      }
    
      async _initialize() {
        // actual async constructor logic
      }
    
      async showPostsOnPage() {
        await this._initialized
        // actual body of the method
      }
    
    }
    

    편집 : 당신은 노드 7 --harmony 플래그 기본적으로이 패턴을 사용할 수 있습니다!


  3. 3.우려의 분리를 방지하기 위해 개체를 만드는 공장을 사용합니다.

    우려의 분리를 방지하기 위해 개체를 만드는 공장을 사용합니다.

    class Engine {
        constructor(data) {
            this.data = data;
        }
    
        static makeEngine(pathToData) {
            return new Promise((resolve, reject) => {
                getData(pathToData).then(data => {
                  resolve(new Engine(data))
                }).catch(reject);
            });
        }
    }
    

  4. 4.생성자에서 반환 값은 약속을 반환하는 것은 좋은 아이디어되지 않도록 new 연산자 단지, 생산하는 객체를 대체합니다. 이전에는 생성자에서 명시 적 반환 값은 싱글 톤 패턴을 사용 하였다.

    생성자에서 반환 값은 약속을 반환하는 것은 좋은 아이디어되지 않도록 new 연산자 단지, 생산하는 객체를 대체합니다. 이전에는 생성자에서 명시 적 반환 값은 싱글 톤 패턴을 사용 하였다.

    ECMAScript를 2017 년 더 나은 방법은 정적 인 방법을 사용하는 것입니다 : 당신은 정적의 numerality 하나 개 프로세스를 가지고있다.

    생성자는 클래스 자체에 알려진 될 수 있습니다 후 어떤 방법은 새 개체에서 실행할 수 있습니다. 클래스 내에서이 문제를 캡슐화하려면 청취자가 추가 Process.launch, 생성자의 호출자에서 다른 것들을 할 수 있도록 허용하는 추가 실행을 연기, process.nextTick 또는 Promise.resolve를 사용할 수 있습니다.

    약속의 거의 모든 코드가 실행의 내부에 있기 때문에 오류가 Process.fatal에 종료됩니다

    이 기본적인 아이디어는 특정 캡슐화 요구에 맞게 수정할 수 있습니다.

    class MyClass {
      constructor(o) {
        if (o == null) o = false
        if (o.run) Promise.resolve()
          .then(() => this.method())
          .then(o.exit).catch(o.reject)
      }
    
      async method() {}
    }
    
    class Process {
      static launch(construct) {
        return new Promise(r => r(
          new construct({run: true, exit: Process.exit, reject: Process.fatal})
        )).catch(Process.fatal)
      }
    
      static exit() {
        process.exit()
      }
    
      static fatal(e) {
        console.error(e.message)
        process.exit(1)
      }
    }
    
    Process.launch(MyClass)
    
  5. from https://stackoverflow.com/questions/24398699/is-it-bad-practice-to-have-a-constructor-function-return-a-promise by cc-by-sa and MIT license