Programing

해결을 시작하지 않고 (ES6) 약속 만들기

lottogame 2021. 1. 7. 07:34
반응형

해결을 시작하지 않고 (ES6) 약속 만들기


ES6 약속을 사용하여 해결 논리를 정의하지 않고 어떻게 약속을 만들 수 있습니까? 다음은 기본 예입니다 (일부 TypeScript).

var promises = {};
function waitFor(key: string): Promise<any> {
  if (key in promises) {
    return promises[key];
  }
  var promise = new Promise(resolve => {
    // But I don't want to try resolving anything here :(
  });

  promises[key] = promise;
  return promise;
}

function resolveWith(key: string, value: any): void {
  promises[key].resolve(value); // Not valid :(
}

다른 promise 라이브러리로 쉽게 수행 할 수 있습니다. 예를 들어 JQuery의 :

var deferreds = {};
function waitFor(key: string): Promise<any> {
  if (key in promises) {
    return deferreds[key].promise();
  }
  var def = $.Deferred();    
  deferreds[key] = def;
  return def.promise();
}

function resolveWith(key: string, value: any): void {
  deferreds[key].resolve(value);
}

이 작업을 수행 할 수있는 유일한 방법은 프라 미스 실행자 내의 어딘가에 resolve 함수를 저장하는 것입니다.하지만 이는 지저분 해 보이며 정확히이 함수가 실행될 때 정의되었는지 확실하지 않습니다. 항상 생성 즉시 실행됩니까?

감사.


좋은 질문!

promise 생성자에 전달 된 확인자는이 사용 사례를 지원하기 위해 의도적으로 동기식으로 실행됩니다.

var deferreds = [];
var p = new Promise(function(resolve, reject){
    deferreds.push({resolve: resolve, reject: reject});
});

그런 다음 나중에 다음과 같이합니다.

 deferreds[0].resolve("Hello"); // resolve the promise with "Hello"

promise 생성자가 제공되는 이유는 다음과 같습니다.

  • 일반적으로 (항상은 아님) 해결 논리가 생성에 바인딩됩니다.
  • promise 생성자는 안전하게 throw되고 예외를 거부로 변환합니다.

때로는 적합하지 않으며이를 위해 리졸버가 동 기적으로 실행됩니다. 다음은 주제에 대한 관련 읽기입니다 .


여기에 2 센트를 더하고 싶습니다. " 해결을 시작하지 않고 es6 Promise 만들기 "라는 질문을 정확히 고려 하여 래퍼 함수를 ​​만들고 대신 래퍼 함수를 ​​호출하여 해결했습니다. 암호:

fPromise를 반환하는 함수가 있다고 가정 해 보겠습니다.

/** @return Promise<any> */
function f(args) {
   return new Promise(....)
}

// calling f()
f('hello', 42).then((response) => { ... })

이제 실제로 해결하지 않고 전화를 준비 하고 싶습니다 f('hello', 42).

const task = () => f('hello', 42) // not calling it actually

// later
task().then((response) => { ... })

이것이 누군가를 도울 수 있기를 바랍니다 :)


Referencing Promise.all() as asked in the comments (and answered by @Joe Frambach), if I want to prepare a call to f1('super') & f2('rainbow'), 2 functions that return promises

const f1 = args => new Promise( ... )
const f2 = args => new Promise( ... )

const tasks = [
  () => f1('super'),
  () => f2('rainbow')
]

// later
Promise.all(tasks.map(t => t()))
  .then(resolvedValues => { ... })

How about a more comprehensive approach?

You could write a Constructor that returns a new Promise decorated with .resolve() and .reject() methods.

You would probably choose to name the constructor Deferred - a term with a lot of precedence in [the history of] javascript promises.

function Deferred(fn) {
    fn = fn || function(){};

    var resolve_, reject_;

    var promise = new Promise(function(resolve, reject) {
        resolve_ = resolve;
        reject_ = reject;
        fn(resolve, reject);
    });

    promise.resolve = function(val) {
        (val === undefined) ? resolve_() : resolve_(val);
        return promise;//for chainability
    }
    promise.reject = function(reason) {
        (reason === undefined) ? reject_() : reject_(reason);
        return promise;//for chainability
    }
    promise.promise = function() {
        return promise.then(); //to derive an undecorated promise (expensive but simple).
    }

    return promise;
}

By returning a decorated promsie rather than a plain object, all the promise's natural methods/properties remain available in addition to the decorations.

Also, by handling fn, the revealer pattern remains availble, should you need/choose to use it on a Deferred.

DEMO

Now, with the Deferred() utility in place, your code is virtually identical to the jQuery example.

var deferreds = {};
function waitFor(key: string): Promise<any> {
  if (key in promises) {
    return deferreds[key].promise();
  }
  var def = Deferred();    
  deferreds[key] = def;
  return def.promise();
}

ReferenceURL : https://stackoverflow.com/questions/31069453/creating-a-es6-promise-without-starting-to-resolve-it

반응형