[javascript] 함수 범위 밖의 Javascript Promise 해결

ES6 Promise를 사용하고 있습니다.

일반적으로 약속은 다음과 같이 구성되고 사용됩니다.

new Promise(function(resolve, reject){
    if (someCondition){
        resolve();
    } else {
        reject();
    } 
});

그러나 유연성을 위해 외부에서 해결하기 위해 아래와 같은 일을 해왔습니다.

var outsideResolve;
var outsideReject;
new Promise(function(resolve, reject) { 
    outsideResolve = resolve; 
    outsideReject = reject; 
});

그리고 나중에

onClick = function(){
    outsideResolve();
}

이것은 잘 작동하지만 더 쉬운 방법이 있습니까? 그렇지 않다면 이것이 좋은 습관입니까?



답변

아니요, 다른 방법은 없습니다. 내가 말할 수있는 유일한 방법은이 사용 사례가 그리 일반적이지 않다는 것입니다. Felix가 의견에서 말했듯이 당신이하는 일은 일관되게 작동합니다.

약속 생성자가 이런 식으로 동작하는 이유는 던지기 안전입니다. 코드가 약속 생성자 내에서 실행되는 동안 예상치 못한 예외가 발생하면 거부,이 형식의 던지기 안전으로 변환됩니다. 거부는 중요하며 예측 가능한 코드를 유지하는 데 도움이됩니다.

이 던지기 안전상의 이유로, 약속 생성자는 지연된 것보다 선택되었습니다 (이것은 당신이하는 일을 허용하는 대체 약속 구성 방법입니다)-모범 사례와 마찬가지로 요소를 전달하고 대신 약속 생성자를 사용합니다.

var p = new Promise(function(resolve, reject){
    this.onclick = resolve;
}.bind(this));

이러한 이유로- 함수를 내보내는 것보다 promise 생성자를 사용할 있을 때마다 사용하는 것이 좋습니다. 둘 다 피할 수있을 때마다-체인과 피하십시오.

약속 생성자를와 같은 용도로 사용해서는 안되며 if(condition)첫 번째 예제는 다음과 같이 작성할 수 있습니다.

var p = Promise[(someCondition)?"resolve":"reject"]();


답변

단순한:

var promiseResolve, promiseReject;

var promise = new Promise(function(resolve, reject){
  promiseResolve = resolve;
  promiseReject = reject;
});

promiseResolve();


답변

여기 파티에 늦었지만 연기 하는 또 다른 방법은 Deferred 객체 를 사용하는 것 입니다. 본질적으로 같은 양의 상용구가 있지만, 그것들을 통과시키고 정의 밖에서 해결할 수 있다면 편리합니다.

순진한 구현 :

class Deferred {
  constructor() {
    this.promise = new Promise((resolve, reject)=> {
      this.reject = reject
      this.resolve = resolve
    })
  }
}

function asyncAction() {
  var dfd = new Deferred()

  setTimeout(()=> {
    dfd.resolve(42)
  }, 500)

  return dfd.promise
}

asyncAction().then(result => {
  console.log(result) // 42
})

ES5 버전 :

function Deferred() {
  var self = this;
  this.promise = new Promise(function(resolve, reject) {
    self.reject = reject
    self.resolve = resolve
  })
}

function asyncAction() {
  var dfd = new Deferred()

  setTimeout(function() {
    dfd.resolve(42)
  }, 500)

  return dfd.promise
}

asyncAction().then(function(result) {
  console.log(result) // 42
})


답변

내 프레임 워크에 대해 2015 년에 생각해 낸 솔루션. 나는 약속의이 유형이라는 작업을

function createPromise(handler){
  var _resolve, _reject;

  var promise = new Promise(function(resolve, reject){
    _resolve = resolve; 
    _reject = reject;

    handler(resolve, reject);
  })

  promise.resolve = _resolve;
  promise.reject = _reject;

  return promise;
}

var promise = createPromise()
promise.then(function(data){ alert(data) })

promise.resolve(200) // resolve from outside


답변

@JonJaques 답변을 좋아했지만 한 단계 더 나아가고 싶었습니다.

당신이 결합하는 경우 thencatch다음 Deferred객체를, 그것은 완전히 구현 PromiseAPI를 당신은 약속로 취급 할 수 있습니다 await그와 같은.

class DeferredPromise {
  constructor() {
    this._promise = new Promise((resolve, reject) => {
      // assign the resolve and reject functions to `this`
      // making them usable on the class instance
      this.resolve = resolve;
      this.reject = reject;
    });
    // bind `then` and `catch` to implement the same interface as Promise
    this.then = this._promise.then.bind(this._promise);
    this.catch = this._promise.catch.bind(this._promise);
    this[Symbol.toStringTag] = 'Promise';
  }
}

const deferred = new DeferredPromise();
console.log('waiting 2 seconds...');
setTimeout(() => {
  deferred.resolve('whoa!');
}, 2000);

async function someAsyncFunction() {
  const value = await deferred;
  console.log(value);
}

someAsyncFunction();


답변

도우미 메소드는 이러한 추가 오버 헤드를 완화하고 동일한 jQuery 느낌을 제공합니다.

function Deferred() {
    let resolve;
    let reject;
    const promise = new Promise((res, rej) => {
        resolve = res;
        reject = rej;
    });
    return { promise, resolve, reject };
}

사용법은

const { promise, resolve, reject } = Deferred();
displayConfirmationDialog({
    confirm: resolve,
    cancel: reject
});
return promise;

jQuery와 비슷한

const dfd = $.Deferred();
displayConfirmationDialog({
    confirm: dfd.resolve,
    cancel: dfd.reject
});
return dfd.promise();

유스 케이스 에서이 간단한 기본 구문은 괜찮습니다.

return new Promise((resolve, reject) => {
    displayConfirmationDialog({
        confirm: resolve,
        cancel: reject
    });
});


답변

헬퍼 함수를 ​​사용하여 “플랫 약속”이라고 부르는 것을 작성하고 있습니다.

function flatPromise() {

    let resolve, reject;

    const promise = new Promise((res, rej) => {
      resolve = res;
      reject = rej;
    });

    return { promise, resolve, reject };
}

그리고 나는 그렇게 사용하고 있습니다-

function doSomethingAsync() {

    // Get your promise and callbacks
    const { resolve, reject, promise } = flatPromise();

    // Do something amazing...
    setTimeout(() => {
        resolve('done!');
    }, 500);

    // Pass your promise to the world
    return promise;

}

전체 작업 예보기-

편집 : flat-promise 라는 NPM 패키지를 만들었 으며 코드는 GitHub 에서도 사용할 수 있습니다 .