[javascript] JavaScript Promise의 상태를 동 기적으로 어떻게 확인할 수 있습니까?

순수한 JavaScript Promise (내장 구현 또는 폴리 필)가 있습니다.

var promise = new Promise(function (resolve, reject) { /* ... */ });

로부터 사양 , 약속은 다음 중 하나 일 수 있습니다 :

  • ‘정착’및 ‘해결’
  • ‘정착’및 ‘거부’
  • ‘보류 중’

약속을 동 기적으로 조사하고 다음을 결정하려는 유스 케이스가 있습니다.

  • 약속이 정 해졌습니까?

  • 그렇다면 약속이 해결 되었습니까?

#then()약속 변경 상태 후에 작업이 비동기 적으로 수행되도록 예약 하는 데 사용할 수 있다는 것을 알고 있습니다 . 이 작업을 수행하는 방법을 묻지 않습니다.

이 질문은 특히 Promise 상태의 동기식 심문에 관한 것 입니다. 어떻게하면 되나요?



답변

기본 JavaScript 약속에 대한 동기 검사 API는 없습니다. 기본 약속으로는 불가능합니다. 사양에서는 이러한 방법을 지정하지 않습니다.

Userland 라이브러리가이를 수행 할 수 있으며 v8과 같은 특정 엔진을 대상으로하고 플랫폼 코드에 액세스 할 수있는 경우 (즉, 핵심 코드를 작성할 수있는 경우) 개인 도구와 같은 특정 도구를 사용하여이를 달성 할 수 있습니다. . 그것은 userland가 아니라 매우 구체적입니다.


답변

여기에 이미지 설명을 입력하십시오

promise-status-async 가 트릭을 수행합니다. 비동기이지만 then약속이 해결되기를 기다리는 데 사용하지 않습니다 .

const {promiseStatus} = require('promise-status-async');
// ...
if (await promiseStatus(promise) === 'pending') {
    const idle = new Promise(function(resolve) {
        // can do some IDLE job meanwhile
    });
    return idle;
}


답변

아니요, 동기화 API는 없지만 promiseState@Matthijs의 도움을 받아 내 비동기 버전을 사용합니다 .

function promiseState(p) {
  const t = {};
  return Promise.race([p, t])
    .then(v => (v === t)? "pending" : "fulfilled", () => "rejected");
}

var a = Promise.resolve();
var b = Promise.reject();
var c = new Promise(() => {});

promiseState(a).then(state => console.log(state)); // fulfilled
promiseState(b).then(state => console.log(state)); // rejected
promiseState(c).then(state => console.log(state)); // pending


답변

Promise.resolve로 경쟁 할 수 있습니다.
동기 적이지는 않지만 지금 발생합니다.

function promiseState(p, isPending, isResolved, isRejected) {
  Promise.race([p, Promise.resolve('a value that p should not return')]).then(function(value) {
    if (value == 'a value that p should not return') {
      (typeof(isPending) === 'function') && isPending();
    }else {
      (typeof(isResolved) === 'function') && isResolved(value);
    }
  }, function(reason) {
    (typeof(isRejected) === 'function') && isRejected(reason);
  });
}

비동기 적으로 그들의 의미를 테스트하고 이해하기위한 작은 스크립트

var startTime = Date.now() - 100000;//padding trick "100001".slice(1) => 00001
function log(msg) {
  console.log((""+(Date.now() - startTime)).slice(1) + ' ' + msg);
  return msg;//for chaining promises
};

function prefix(pref) { return function (value) { log(pref + value); return value; };}

function delay(ms) {
  return function (value) {
    var startTime = Date.now();
    while(Date.now() - startTime < ms) {}
    return value;//for chaining promises
  };
}
setTimeout(log, 0,'timeOut 0 ms');
setTimeout(log, 100,'timeOut 100 ms');
setTimeout(log, 200,'timeOut 200 ms');

var p1 = Promise.resolve('One');
var p2 = new Promise(function(resolve, reject) { setTimeout(resolve, 100, "Two"); });
var p3 = Promise.reject("Three");

p3.catch(delay(200)).then(delay(100)).then(prefix('delayed L3 : '));

promiseState(p1, prefix('p1 Is Pending '), prefix('p1 Is Resolved '), prefix('p1 Is Rejected '));
promiseState(p2, prefix('p2 Is Pending '), prefix('p2 Is Resolved '), prefix('p2 Is Rejected '));
promiseState(p3, prefix('p3 Is Pending '), prefix('p3 Is Resolved '), prefix('p3 Is Rejected '));

p1.then(prefix('Level 1 : ')).then(prefix('Level 2 : ')).then(prefix('Level 3 : '));
p2.then(prefix('Level 1 : ')).then(prefix('Level 2 : ')).then(prefix('Level 3 : '));
p3.catch(prefix('Level 1 : ')).then(prefix('Level 2 : ')).then(prefix('Level 3 : '));
log('end of promises');
delay(100)();
log('end of script');

delay (0)의 결과 (지연된 동안 주석 처리)

00001 end of promises
00001 end of script
00001 Level 1 : One
00001 Level 1 : Three
00001 p1 Is Resolved One
00001 p2 Is Pending undefined
00001 p3 Is Rejected Three
00001 Level 2 : One
00001 Level 2 : Three
00001 delayed L3 : Three
00002 Level 3 : One
00002 Level 3 : Three
00006 timeOut 0 ms
00100 timeOut 100 ms
00100 Level 1 : Two
00100 Level 2 : Two
00101 Level 3 : Two
00189 timeOut 200 ms

파이어 폭스 (크롬 순서를 유지) 와이 테스트의 결과

00000 end of promises
00100 end of script
00300 Level 1 : One
00300 Level 1 : Three
00400 p1 Is Resolved One
00400 p2 Is Pending undefined
00400 p3 Is Rejected Three
00400 Level 2 : One
00400 Level 2 : Three
00400 delayed L3 : Three
00400 Level 3 : One
00400 Level 3 : Three
00406 timeOut 0 ms
00406 timeOut 100 ms
00406 timeOut 200 ms
00406 Level 1 : Two
00407 Level 2 : Two
00407 Level 3 : Two

promiseState make .race 및 .then : 레벨 2


답변

기본 메소드가 제공 될 때까지 Node.js에서 (못생긴) 핵을 사용할 수 있습니다.

util = require('util');

var promise1 = new Promise (function (resolve) {
}

var promise2 = new Promise (function (resolve) {

    resolve ('foo');
}

state1 = util.inspect (promise1);
state2 = util.inspect (promise2);

if (state1 === 'Promise { <pending> }') {

    console.log('pending'); // pending
}

if (state2 === "Promise { 'foo' }") {

    console.log ('foo') // foo
}


답변

노드에서 문서화되지 않은 내부 라고 말하십시오. process.binding('util').getPromiseDetails(promise)

> process.binding('util').getPromiseDetails(Promise.resolve({data: [1,2,3]}));
[ 1, { data: [ 1, 2, 3 ] } ]

> process.binding('util').getPromiseDetails(Promise.reject(new Error('no')));
[ 2, Error: no ]

> process.binding('util').getPromiseDetails(new Promise((resolve) => {}));
[ 0, <1 empty item> ]


답변

업데이트 : 2019

Bluebird.js는 다음을 제공합니다. http://bluebirdjs.com/docs/api/isfulfilled.html

var Promise = require("bluebird");
let p = Promise.resolve();
console.log(p.isFulfilled());

자신 만의 래퍼를 만들고 싶다면 여기에 좋은 블로그 가 있습니다.

JavaScript는 단일 스레드이기 때문에 사양에 넣는 것을 정당화하기에 충분한 일반적인 사용 사례를 찾기가 어렵습니다. 약속이 해결되었는지 알 수있는 가장 좋은 곳은 .then ()입니다. 약속이 꽉 찼는 지 테스트하면 폴링 루프가 만들어져 잘못된 방향 일 가능성이 큽니다.

async / await 는 비동기 코드를 동 기적으로 추론하려는 경우 훌륭한 구성입니다.

await this();
await that();
return 'success!';

또 다른 유용한 호출은 Promise.all ()

var promise1 = Promise.resolve(3);
var promise2 = 42;
var promise3 = new Promise(function(resolve, reject) {
  setTimeout(resolve, 100, 'foo');
});

Promise.all([promise1, promise2, promise3]).then(function(values) {
  console.log(values);
});
// expected output: Array [3, 42, "foo"]

이 답변에 처음 도달했을 때, 이것이 내가 찾던 사용 사례입니다.