I have a pure JavaScript Promise (built-in implementation or poly-fill):
我有一个纯JavaScript承诺(内置实现或poly-fill):
var promise = new Promise(function (resolve, reject) { /* ... */ });
var promise = new Promise(function(resolve,reject){/ * ... * /});
From the specification, a Promise can be one of:
根据规范,Promise可以是以下之一:
- 'settled' and 'resolved'
- '已定居'和'已解决'
- 'settled' and 'rejected'
- '已定居'和'被拒绝'
- 'pending'
- “待定”
I have a use case where I wish to interrogate the Promise synchronously and determine:
我有一个用例,我希望同步询问Promise并确定:
-
is the Promise settled?
承诺解决了吗?
-
if so, is the Promise resolved?
如果是这样,Promise是否已解决?
I know that I can use #then()
to schedule work to be performed asynchronously after the Promise changes state. I am NOT asking how to do this.
我知道我可以使用#then()来安排在Promise更改状态后异步执行的工作。我不是问怎么做。
This question is specifically about synchronous interrogation of a Promise's state. How can I achieve this?
这个问题具体是关于对Promise状态的同步审讯。我怎样才能做到这一点?
14 个解决方案
#1
44
No such synchronous inspection API exists for native JavaScript promises. It is impossible to do this with native promises. The specification does not specify such a method.
对于本机JavaScript承诺,不存在此类同步检查API。用本机承诺做这件事是不可能的。规范没有指定这样的方法。
Userland libraries can do this, and if you're targeting a specific engine (like v8) and have access to platform code (that is, you can write code in core) then you can use specific tools (like private symbols) to achieve this. That's super specific though and not in userland.
Userland库可以做到这一点,如果您的目标是特定引擎(如v8)并且可以访问平台代码(也就是说,您可以在核心中编写代码),那么您可以使用特定工具(如私有符号)来实现此目的。这是超级特定的,而不是用户区。
#2
13
You can make a race with Promise.resolve
It's not synchronous but happens now
你可以用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);
});
}
A little script for testing and understand their meaning of asynchronously
一个小脚本,用于测试和理解它们异步的含义
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');
results with delay(0) (comment the while in 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
and the results of this test with firefox(chrome keep the order)
和firefox的这个测试结果(chrome保持顺序)
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 and .then : Level 2
promiseState make .race和.then:Level 2
#3
11
Nope, no sync API, but here's my version of the async promiseState
(with help from @Matthijs):
不,没有同步API,但这是我的async 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
#4
6
You can use an (ugly) hack in Node.js until a native method is offered:
您可以在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
}
#5
4
You can wrap your promises in this way
你可以用这种方式包装你的承诺
function wrapPromise(promise) {
var value, error,
settled = false,
resolved = false,
rejected = false,
p = promise.then(function(v) {
value = v;
settled = true;
resolved = true;
return v;
}, function(err) {
error = err;
settled = true;
rejected = true;
throw err;
});
p.isSettled = function() {
return settled;
};
p.isResolved = function() {
return resolved;
};
p.isRejected = function() {
return rejected;
};
p.value = function() {
return value;
};
p.error = function() {
return error;
};
var pThen = p.then, pCatch = p.catch;
p.then = function(res, rej) {
return wrapPromise(pThen(res, rej));
};
p.catch = function(rej) {
return wrapPromise(pCatch(rej));
};
return p;
}
#6
2
Bluebird.js offers this: http://bluebirdjs.com/docs/api/isfulfilled.html
Bluebird.js提供了这个:http://bluebirdjs.com/docs/api/isfulfilled.html
var Promise = require("bluebird");
let p = Promise.resolve();
console.log(p.isFulfilled());
#7
2
what you can do, is to use a variable to store the state, manually set the state to that variable, and check that variable.
您可以做的是使用变量来存储状态,手动将状态设置为该变量,并检查该变量。
var state = 'pending';
new Promise(function(ff, rjc) {
//do something async
if () {//if success
state = 'resolved';
ff();//
} else {
state = 'rejected';
rjc();
}
});
console.log(state);//check the state somewhere else in the code
of course, this means you must have access to the original code of the promise. If you don't, then you can do:
当然,这意味着您必须能够访问承诺的原始代码。如果你不这样做,那么你可以这样做:
var state = 'pending';
//you can't access somePromise's code
somePromise.then(function(){
state = 'resolved';
}, function() {
state = 'rejected';
})
console.log(state);//check the promise's state somewhere else in the code
My solution is more coding, but I think you probably wouldn't have to do this for every promise you use.
我的解决方案是更多编码,但我认为您可能不必为您使用的每个承诺执行此操作。
#8
2
It's indeed quite annoying that this basic functionality is missing. If you're using node.js then I know of two workarounds, neither of 'em very pretty. Both snippets below implement the same API:
这个基本功能缺失确实令人讨厌。如果您正在使用node.js,那么我知道两个解决方法,它们都不是很漂亮。以下两个代码段都实现了相同的API:
> Promise.getInfo( 42 ) // not a promise
{ status: 'fulfilled', value: 42 }
> Promise.getInfo( Promise.resolve(42) ) // fulfilled
{ status: 'fulfilled', value: 42 }
> Promise.getInfo( Promise.reject(42) ) // rejected
{ status: 'rejected', value: 42 }
> Promise.getInfo( p = new Promise(() => {}) ) // unresolved
{ status: 'pending' }
> Promise.getInfo( Promise.resolve(p) ) // resolved but pending
{ status: 'pending' }
There doesn't seem to be any way to distinguish the last two promise states using either trick.
似乎没有任何方法可以使用任何一种技巧来区分最后两个承诺状态。
1. Use the V8 debug API
This is the same trick that util.inspect
uses.
这与util.inspect使用的技巧相同。
const Debug = require('vm').runInDebugContext('Debug');
Promise.getInfo = function( arg ) {
let mirror = Debug.MakeMirror( arg, true );
if( ! mirror.isPromise() )
return { status: 'fulfilled', value: arg };
let status = mirror.status();
if( status === 'pending' )
return { status };
if( status === 'resolved' ) // fix terminology fuck-up
status = 'fulfilled';
let value = mirror.promiseValue().value();
return { status, value };
};
2. Synchronously run microtasks
This avoids the debug API, but has some frightening semantics by causing all pending microtasks and process.nextTick
callbacks to be run synchronously. It also has the side-effect of preventing the "unhandled promise rejection" error from ever being triggered for the inspected promise.
这避免了调试API,但通过使所有挂起的微任务和process.nextTick回调同步运行,具有一些可怕的语义。它还具有防止未经检查的承诺触发“未处理的承诺拒绝”错误的副作用。
Promise.getInfo = function( arg ) {
const pending = {};
let status, value;
Promise.race([ arg, pending ]).then(
x => { status = 'fulfilled'; value = x; },
x => { status = 'rejected'; value = x; }
);
process._tickCallback(); // run microtasks right now
if( value === pending )
return { status: 'pending' };
return { status, value };
};
#9
2
As of Node.js version 8, you can now use the wise-inspection package to synchronously inspect native promises (without any dangerous hacks).
从Node.js版本8开始,您现在可以使用明智检查包来同步检查本机承诺(没有任何危险的黑客攻击)。
#10
2
You can add a method to Promise.prototype. It looks like this:
您可以向Promise.prototype添加方法。它看起来像这样:
Edited: The first solution is not working properly, like most of the answers here. It returns "pending" until the asynchronous function ".then" is invoked, which is not happen immediately. (The same is about solutions using Promise.race). My second solution solves this problem.
编辑:第一个解决方案不能正常工作,就像这里的大部分答案一样。它返回“pending”,直到调用异步函数“.then”,这不会立即发生。 (同样是关于使用Promise.race的解决方案)。我的第二个解决方案解决了这个问题
if (window.Promise) {
Promise.prototype.getState = function () {
if (!this.state) {
this.state = "pending";
var that = this;
this.then(
function (v) {
that.state = "resolved";
return v;
},
function (e) {
that.state = "rejected";
return e;
});
}
return this.state;
};
}
You can use it on any Promise. For exemple:
你可以在任何Promise上使用它。举个例子:
myPromise = new Promise(myFunction);
console.log(myPromise.getState()); // pending|resolved|rejected
Second (and correct) solution:
第二(和正确)的解决方案:
if (window.Promise) {
Promise.stateable = function (func) {
var state = "pending";
var pending = true;
var newPromise = new Promise(wrapper);
newPromise.state = state;
return newPromise;
function wrapper(resolve, reject) {
func(res, rej);
function res(e) {
resolve(e);
if (pending) {
if (newPromise)
newPromise.state = "resolved";
else
state = "resolved";
pending = false;
}
}
function rej(e) {
reject(e);
if (pending) {
if (newPromise)
newPromise.state = "rejected";
else
state = "rejected";
pending = false;
}
}
}
};
}
And use it:
并使用它:
Notice: In this solution you doesn't have to use the "new" operator.
注意:在此解决方案中,您不必使用“new”运算符。
myPromise = Promise.stateable(myFunction);
console.log(myPromise.state); // pending|resolved|rejected
#11
1
in node, say process.binding('util').getPromiseDetails(promise)
在节点中,比如process.binding('util')。getPromiseDetails(promise)
#12
0
If you're using ES7 experimental you can use async to easily wrap the promise you want to listen.
如果你正在使用ES7实验,你可以使用async轻松包装你想听的诺言。
async function getClient() {
let client, resolved = false;
try {
client = await new Promise((resolve, reject) => {
let client = new Client();
let timer = setTimeout(() => {
reject(new Error(`timeout`, 1000));
client.close();
});
client.on('ready', () => {
if(!resolved) {
clearTimeout(timer);
resolve(client);
}
});
client.on('error', (error) => {
if(!resolved) {
clearTimeout(timer);
reject(error);
}
});
client.on('close', (hadError) => {
if(!resolved && !hadError) {
clearTimeout(timer);
reject(new Error("close"));
}
});
});
resolved = true;
} catch(error) {
resolved = true;
throw error;
}
return client;
}
#13
0
I've written a little npm package, promise-value, which provides a promise wrapper with a resolved
flag:
我写了一个小的npm包,promise-value,它提供了一个带有已解析标志的promise包装器:
https://www.npmjs.com/package/promise-value
https://www.npmjs.com/package/promise-value
It also gives synchronous access to the promise value (or error). This doesn't alter the Promise object itself, following the wrap rather than extend pattern.
它还提供对promise值(或错误)的同步访问。这不会改变Promise对象本身,而是在wrap而不是extend模式之后。
#14
0
This is older question but I was trying to do something similar. I need to keep n workers going. They are structured in a promise. I need to scan and see if they are resolved, rejected or still pending. If resolved, I need the value, if rejected do something to correct the issue or pending. If resolved or rejected I need to start another task to keep n going. I can't figure a way to do it with Promise.all or Promise.race as I keep working promises in an array and can find no way to delete them. So I create a worker that does the trick
这是一个较老的问题,但我试图做类似的事情。我需要让n工人继续前进。它们的结构是承诺。我需要扫描并查看它们是否已被解决,被拒绝或仍未决定。如果已经解决,我需要该值,如果被拒绝做某事来纠正问题或待决。如果解决或拒绝,我需要开始另一项任务以保持正常。我无法想办法用Promise.all或Promise.race做这件事,因为我继续在数组中使用promises并且找不到删除它们的方法。所以我创造了一个能够解决问题的工人
I need a promise generator function that returns a promise which resolves or rejects as necessary. It is called by a function that sets up the framework to know what the promise is doing.
我需要一个promise生成器函数,它返回一个在必要时解析或拒绝的promise。它由一个函数调用,该函数设置框架以了解承诺正在做什么。
In the code below the generator simply returns a promise based on setTimeout.
在下面的代码中,生成器只返回基于setTimeout的promise。
Here it is
这里是
//argObj should be of form
// {succeed: <true or false, nTimer: <desired time out>}
function promiseGenerator(argsObj) {
let succeed = argsObj.succeed;
let nTimer = argsObj.nTimer;
return new Promise((resolve, reject) => {
setTimeout(() => {
if (succeed) {
resolve('ok');
}
else {
reject(`fail`);
}
}, nTimer);
})
}
function doWork(generatorargs) {
let sp = { state: `pending`, value: ``, promise: "" };
let p1 = promiseGenerator(generatorargs)
.then((value) => {
sp.state = "resolved";
sp.value = value;
})
.catch((err) => {
sp.state = "rejected";
sp.value = err;
})
sp.promise = p1;
return sp;
}
doWork returns an object containing the promise and the its state and returned value.
doWork返回一个包含promise及其状态和返回值的对象。
The following code runs a loop that tests the state and creates new workers to keep it at 3 running workers.
以下代码运行一个循环,该循环测试状态并创建新工作程序以使其保持在3个正在运行的工作程序。
let promiseArray = [];
promiseArray.push(doWork({ succeed: true, nTimer: 1000 }));
promiseArray.push(doWork({ succeed: true, nTimer: 500 }));
promiseArray.push(doWork({ succeed: false, nTimer: 3000 }));
function loopTimerPromise(delay) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('ok');
}, delay)
})
}
async function looper() {
let nPromises = 3; //just for breaking loop
let nloop = 0; //just for breaking loop
let i;
//let continueLoop = true;
while (true) {
await loopTimerPromise(900); //execute loop every 900ms
nloop++;
//console.log(`promiseArray.length = ${promiseArray.length}`);
for (i = promiseArray.length; i--; i > -1) {
console.log(`index ${i} state: ${promiseArray[i].state}`);
switch (promiseArray[i].state) {
case "pending":
break;
case "resolved":
nPromises++;
promiseArray.splice(i, 1);
promiseArray.push(doWork({ succeed: true, nTimer: 1000 }));
break;
case "rejected":
//take recovery action
nPromises++;
promiseArray.splice(i, 1);
promiseArray.push(doWork({ succeed: false, nTimer: 500 }));
break;
default:
console.log(`error bad state in i=${i} state:${promiseArray[i].state} `)
break;
}
}
console.log(``);
if (nloop > 10 || nPromises > 10) {
//should do a Promise.all on remaining promises to clean them up but not for test
break;
}
}
}
looper();
Tested in node.js
在node.js中测试
BTW Not in this answer so much but in others on similar topics, I HATE it when someone says "you don't understand" or "that's not how it works" I generally assume the questioner knows what they want. Suggesting a better way is great. A patient explanation of how promises work would also be good.
顺便说一下这个答案不是很多,但是在其他类似主题的答案中,当有人说“你不理解”或“那不是它的工作原理”时,我讨厌它。我通常认为提问者知道他们想要什么。建议一个更好的方法是伟大的。关于承诺如何运作的患者解释也将是好的。
#1
44
No such synchronous inspection API exists for native JavaScript promises. It is impossible to do this with native promises. The specification does not specify such a method.
对于本机JavaScript承诺,不存在此类同步检查API。用本机承诺做这件事是不可能的。规范没有指定这样的方法。
Userland libraries can do this, and if you're targeting a specific engine (like v8) and have access to platform code (that is, you can write code in core) then you can use specific tools (like private symbols) to achieve this. That's super specific though and not in userland.
Userland库可以做到这一点,如果您的目标是特定引擎(如v8)并且可以访问平台代码(也就是说,您可以在核心中编写代码),那么您可以使用特定工具(如私有符号)来实现此目的。这是超级特定的,而不是用户区。
#2
13
You can make a race with Promise.resolve
It's not synchronous but happens now
你可以用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);
});
}
A little script for testing and understand their meaning of asynchronously
一个小脚本,用于测试和理解它们异步的含义
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');
results with delay(0) (comment the while in 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
and the results of this test with firefox(chrome keep the order)
和firefox的这个测试结果(chrome保持顺序)
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 and .then : Level 2
promiseState make .race和.then:Level 2
#3
11
Nope, no sync API, but here's my version of the async promiseState
(with help from @Matthijs):
不,没有同步API,但这是我的async 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
#4
6
You can use an (ugly) hack in Node.js until a native method is offered:
您可以在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
}
#5
4
You can wrap your promises in this way
你可以用这种方式包装你的承诺
function wrapPromise(promise) {
var value, error,
settled = false,
resolved = false,
rejected = false,
p = promise.then(function(v) {
value = v;
settled = true;
resolved = true;
return v;
}, function(err) {
error = err;
settled = true;
rejected = true;
throw err;
});
p.isSettled = function() {
return settled;
};
p.isResolved = function() {
return resolved;
};
p.isRejected = function() {
return rejected;
};
p.value = function() {
return value;
};
p.error = function() {
return error;
};
var pThen = p.then, pCatch = p.catch;
p.then = function(res, rej) {
return wrapPromise(pThen(res, rej));
};
p.catch = function(rej) {
return wrapPromise(pCatch(rej));
};
return p;
}
#6
2
Bluebird.js offers this: http://bluebirdjs.com/docs/api/isfulfilled.html
Bluebird.js提供了这个:http://bluebirdjs.com/docs/api/isfulfilled.html
var Promise = require("bluebird");
let p = Promise.resolve();
console.log(p.isFulfilled());
#7
2
what you can do, is to use a variable to store the state, manually set the state to that variable, and check that variable.
您可以做的是使用变量来存储状态,手动将状态设置为该变量,并检查该变量。
var state = 'pending';
new Promise(function(ff, rjc) {
//do something async
if () {//if success
state = 'resolved';
ff();//
} else {
state = 'rejected';
rjc();
}
});
console.log(state);//check the state somewhere else in the code
of course, this means you must have access to the original code of the promise. If you don't, then you can do:
当然,这意味着您必须能够访问承诺的原始代码。如果你不这样做,那么你可以这样做:
var state = 'pending';
//you can't access somePromise's code
somePromise.then(function(){
state = 'resolved';
}, function() {
state = 'rejected';
})
console.log(state);//check the promise's state somewhere else in the code
My solution is more coding, but I think you probably wouldn't have to do this for every promise you use.
我的解决方案是更多编码,但我认为您可能不必为您使用的每个承诺执行此操作。
#8
2
It's indeed quite annoying that this basic functionality is missing. If you're using node.js then I know of two workarounds, neither of 'em very pretty. Both snippets below implement the same API:
这个基本功能缺失确实令人讨厌。如果您正在使用node.js,那么我知道两个解决方法,它们都不是很漂亮。以下两个代码段都实现了相同的API:
> Promise.getInfo( 42 ) // not a promise
{ status: 'fulfilled', value: 42 }
> Promise.getInfo( Promise.resolve(42) ) // fulfilled
{ status: 'fulfilled', value: 42 }
> Promise.getInfo( Promise.reject(42) ) // rejected
{ status: 'rejected', value: 42 }
> Promise.getInfo( p = new Promise(() => {}) ) // unresolved
{ status: 'pending' }
> Promise.getInfo( Promise.resolve(p) ) // resolved but pending
{ status: 'pending' }
There doesn't seem to be any way to distinguish the last two promise states using either trick.
似乎没有任何方法可以使用任何一种技巧来区分最后两个承诺状态。
1. Use the V8 debug API
This is the same trick that util.inspect
uses.
这与util.inspect使用的技巧相同。
const Debug = require('vm').runInDebugContext('Debug');
Promise.getInfo = function( arg ) {
let mirror = Debug.MakeMirror( arg, true );
if( ! mirror.isPromise() )
return { status: 'fulfilled', value: arg };
let status = mirror.status();
if( status === 'pending' )
return { status };
if( status === 'resolved' ) // fix terminology fuck-up
status = 'fulfilled';
let value = mirror.promiseValue().value();
return { status, value };
};
2. Synchronously run microtasks
This avoids the debug API, but has some frightening semantics by causing all pending microtasks and process.nextTick
callbacks to be run synchronously. It also has the side-effect of preventing the "unhandled promise rejection" error from ever being triggered for the inspected promise.
这避免了调试API,但通过使所有挂起的微任务和process.nextTick回调同步运行,具有一些可怕的语义。它还具有防止未经检查的承诺触发“未处理的承诺拒绝”错误的副作用。
Promise.getInfo = function( arg ) {
const pending = {};
let status, value;
Promise.race([ arg, pending ]).then(
x => { status = 'fulfilled'; value = x; },
x => { status = 'rejected'; value = x; }
);
process._tickCallback(); // run microtasks right now
if( value === pending )
return { status: 'pending' };
return { status, value };
};
#9
2
As of Node.js version 8, you can now use the wise-inspection package to synchronously inspect native promises (without any dangerous hacks).
从Node.js版本8开始,您现在可以使用明智检查包来同步检查本机承诺(没有任何危险的黑客攻击)。
#10
2
You can add a method to Promise.prototype. It looks like this:
您可以向Promise.prototype添加方法。它看起来像这样:
Edited: The first solution is not working properly, like most of the answers here. It returns "pending" until the asynchronous function ".then" is invoked, which is not happen immediately. (The same is about solutions using Promise.race). My second solution solves this problem.
编辑:第一个解决方案不能正常工作,就像这里的大部分答案一样。它返回“pending”,直到调用异步函数“.then”,这不会立即发生。 (同样是关于使用Promise.race的解决方案)。我的第二个解决方案解决了这个问题
if (window.Promise) {
Promise.prototype.getState = function () {
if (!this.state) {
this.state = "pending";
var that = this;
this.then(
function (v) {
that.state = "resolved";
return v;
},
function (e) {
that.state = "rejected";
return e;
});
}
return this.state;
};
}
You can use it on any Promise. For exemple:
你可以在任何Promise上使用它。举个例子:
myPromise = new Promise(myFunction);
console.log(myPromise.getState()); // pending|resolved|rejected
Second (and correct) solution:
第二(和正确)的解决方案:
if (window.Promise) {
Promise.stateable = function (func) {
var state = "pending";
var pending = true;
var newPromise = new Promise(wrapper);
newPromise.state = state;
return newPromise;
function wrapper(resolve, reject) {
func(res, rej);
function res(e) {
resolve(e);
if (pending) {
if (newPromise)
newPromise.state = "resolved";
else
state = "resolved";
pending = false;
}
}
function rej(e) {
reject(e);
if (pending) {
if (newPromise)
newPromise.state = "rejected";
else
state = "rejected";
pending = false;
}
}
}
};
}
And use it:
并使用它:
Notice: In this solution you doesn't have to use the "new" operator.
注意:在此解决方案中,您不必使用“new”运算符。
myPromise = Promise.stateable(myFunction);
console.log(myPromise.state); // pending|resolved|rejected
#11
1
in node, say process.binding('util').getPromiseDetails(promise)
在节点中,比如process.binding('util')。getPromiseDetails(promise)
#12
0
If you're using ES7 experimental you can use async to easily wrap the promise you want to listen.
如果你正在使用ES7实验,你可以使用async轻松包装你想听的诺言。
async function getClient() {
let client, resolved = false;
try {
client = await new Promise((resolve, reject) => {
let client = new Client();
let timer = setTimeout(() => {
reject(new Error(`timeout`, 1000));
client.close();
});
client.on('ready', () => {
if(!resolved) {
clearTimeout(timer);
resolve(client);
}
});
client.on('error', (error) => {
if(!resolved) {
clearTimeout(timer);
reject(error);
}
});
client.on('close', (hadError) => {
if(!resolved && !hadError) {
clearTimeout(timer);
reject(new Error("close"));
}
});
});
resolved = true;
} catch(error) {
resolved = true;
throw error;
}
return client;
}
#13
0
I've written a little npm package, promise-value, which provides a promise wrapper with a resolved
flag:
我写了一个小的npm包,promise-value,它提供了一个带有已解析标志的promise包装器:
https://www.npmjs.com/package/promise-value
https://www.npmjs.com/package/promise-value
It also gives synchronous access to the promise value (or error). This doesn't alter the Promise object itself, following the wrap rather than extend pattern.
它还提供对promise值(或错误)的同步访问。这不会改变Promise对象本身,而是在wrap而不是extend模式之后。
#14
0
This is older question but I was trying to do something similar. I need to keep n workers going. They are structured in a promise. I need to scan and see if they are resolved, rejected or still pending. If resolved, I need the value, if rejected do something to correct the issue or pending. If resolved or rejected I need to start another task to keep n going. I can't figure a way to do it with Promise.all or Promise.race as I keep working promises in an array and can find no way to delete them. So I create a worker that does the trick
这是一个较老的问题,但我试图做类似的事情。我需要让n工人继续前进。它们的结构是承诺。我需要扫描并查看它们是否已被解决,被拒绝或仍未决定。如果已经解决,我需要该值,如果被拒绝做某事来纠正问题或待决。如果解决或拒绝,我需要开始另一项任务以保持正常。我无法想办法用Promise.all或Promise.race做这件事,因为我继续在数组中使用promises并且找不到删除它们的方法。所以我创造了一个能够解决问题的工人
I need a promise generator function that returns a promise which resolves or rejects as necessary. It is called by a function that sets up the framework to know what the promise is doing.
我需要一个promise生成器函数,它返回一个在必要时解析或拒绝的promise。它由一个函数调用,该函数设置框架以了解承诺正在做什么。
In the code below the generator simply returns a promise based on setTimeout.
在下面的代码中,生成器只返回基于setTimeout的promise。
Here it is
这里是
//argObj should be of form
// {succeed: <true or false, nTimer: <desired time out>}
function promiseGenerator(argsObj) {
let succeed = argsObj.succeed;
let nTimer = argsObj.nTimer;
return new Promise((resolve, reject) => {
setTimeout(() => {
if (succeed) {
resolve('ok');
}
else {
reject(`fail`);
}
}, nTimer);
})
}
function doWork(generatorargs) {
let sp = { state: `pending`, value: ``, promise: "" };
let p1 = promiseGenerator(generatorargs)
.then((value) => {
sp.state = "resolved";
sp.value = value;
})
.catch((err) => {
sp.state = "rejected";
sp.value = err;
})
sp.promise = p1;
return sp;
}
doWork returns an object containing the promise and the its state and returned value.
doWork返回一个包含promise及其状态和返回值的对象。
The following code runs a loop that tests the state and creates new workers to keep it at 3 running workers.
以下代码运行一个循环,该循环测试状态并创建新工作程序以使其保持在3个正在运行的工作程序。
let promiseArray = [];
promiseArray.push(doWork({ succeed: true, nTimer: 1000 }));
promiseArray.push(doWork({ succeed: true, nTimer: 500 }));
promiseArray.push(doWork({ succeed: false, nTimer: 3000 }));
function loopTimerPromise(delay) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('ok');
}, delay)
})
}
async function looper() {
let nPromises = 3; //just for breaking loop
let nloop = 0; //just for breaking loop
let i;
//let continueLoop = true;
while (true) {
await loopTimerPromise(900); //execute loop every 900ms
nloop++;
//console.log(`promiseArray.length = ${promiseArray.length}`);
for (i = promiseArray.length; i--; i > -1) {
console.log(`index ${i} state: ${promiseArray[i].state}`);
switch (promiseArray[i].state) {
case "pending":
break;
case "resolved":
nPromises++;
promiseArray.splice(i, 1);
promiseArray.push(doWork({ succeed: true, nTimer: 1000 }));
break;
case "rejected":
//take recovery action
nPromises++;
promiseArray.splice(i, 1);
promiseArray.push(doWork({ succeed: false, nTimer: 500 }));
break;
default:
console.log(`error bad state in i=${i} state:${promiseArray[i].state} `)
break;
}
}
console.log(``);
if (nloop > 10 || nPromises > 10) {
//should do a Promise.all on remaining promises to clean them up but not for test
break;
}
}
}
looper();
Tested in node.js
在node.js中测试
BTW Not in this answer so much but in others on similar topics, I HATE it when someone says "you don't understand" or "that's not how it works" I generally assume the questioner knows what they want. Suggesting a better way is great. A patient explanation of how promises work would also be good.
顺便说一下这个答案不是很多,但是在其他类似主题的答案中,当有人说“你不理解”或“那不是它的工作原理”时,我讨厌它。我通常认为提问者知道他们想要什么。建议一个更好的方法是伟大的。关于承诺如何运作的患者解释也将是好的。