순수한 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"]
이 답변에 처음 도달했을 때, 이것이 내가 찾던 사용 사례입니다.