Я просмотрел решения, предложенные для этого вопроса, и не нашел ни одного, соответствующего простому подходу, который я использовал в Node.js.
Я определил простой класс PromiseMonitor, который принимает промис в качестве единственного параметра для своего конструктора и имеет строковое свойство .status
, которое возвращает стандартные строковые значения, соответствующие статусу промиса: ожидание, разрешение или отклонение, и четыре логических свойства .pending
, .resolved
, .rejected
и .error
. Свойство .error
устанавливается в значение true, только если .rejected
равно true и обратному вызову отклонения был передан объект Error.
Класс просто использует .then()
в обещании, чтобы изменить статус PromiseMonitor, когда обещание разрешено или отклонено. Это не мешает любому другому использованию исходного промиса. Вот код:
class PromiseMonitor {
constructor(prm){
this._status = "pending";
this._pending = true;
this._resolved = false;
this._rejected = false;
this._error = false;
prm
.then( ()=>{
this._status = "resolved";
this._resolved = true;
this._pending = false;
}
, (err)=>{
this._status = "rejected";
this._pending = false;
this._rejected = true;
this._error = err instanceof Error ? true: false ;
}
);
}
get status(){ return this._status; };
get pending(){ return this._pending; };
get resolved(){ return this._resolved; };
get rejected(){ return this._rejected; };
get error(){ return this._error };
};
Чтобы отслеживать статус обещания, просто создайте экземпляр PromiseMonitor, передав обещание в качестве параметра, например:
let promiseObject = functionThatReturnsAPromise();
let promiseMonitor = new PromiseMonitor( promiseObject );
Теперь вы можете синхронно проверять все свойства promiseMonitor, которые будут отслеживать статус исходного промиса. Вот тестовый сценарий, демонстрирующий три возможных разрешения отслеживаемого промиса.
let ticks = 0;
let tickerID = setInterval( ()=>{++ticks; console.log(`..tick ${ticks}`)}, 1000);
async function run(){
console.log("Start");
let delay = prmDelay(2000);
let delayMonitor = new PromiseMonitor(delay);
// normal handling of delay promise
delay.then((result)=>( console.log("Normal resolution of delay using .then()") ) );
console.log("delay at start:\n", delay);
console.log("delayMonitor at start:\n", delayMonitor);
await delay;
console.log("delay finished:\n", delay);
console.log("delayMonitor finished:\n", delayMonitor);
console.log("\n\n TEST2: Rejection without an Error test ================================")
let rejDelay = prmDelay(3000, "reject");
let rejMonitor = new PromiseMonitor(rejDelay);
// normal handling of reject result on promise
rejDelay.then((result)=>( console.log("Normal resolution of rejDelay using .then will not happen") )
, (err)=>( console.log("Rejection of rejDelay handled using .then")));
console.log("rejDelay at start:\n", rejDelay);
console.log("rejMonitor at start:\n", rejMonitor);
await rejDelay.catch( (err)=>{ console.log( "Caught error using .catch on rejDelay" ); });
console.log("rejDelay finished:\n", rejDelay);
console.log("rejMonitor finished:\n", rejMonitor);
console.log("\n\n TEST3: Rejection with an Error test ================================")
let errMonitor ;
let errDelay;
try{
errDelay = prmDelay(1000, "error");
errMonitor = new PromiseMonitor(errDelay);
// normal handling of results of the original promise
errDelay.then(
(result)=>{
console.log("Normal expiry of errDelay");
console.log("Monitor Status is " + errMonitor.status )
}
, (err)=>{
console.log("** Rejection of errDelay handled using .then()");
console.log(" Monitor Status is " + errMonitor.status )
}
);
console.log("errDelay at start:\n", errDelay);
console.log("errMonitor at start:\n", errMonitor);
await errDelay;
console.log("**** This should never be run");
} catch(err) {
console.log( "** Caught error on errDelay using try{}catch{}:" );
console.log( " Monitor Status is " + errMonitor.status )
};
console.log("errDelay finished:\n", errDelay);
console.log("errMonitor finished:\n", errMonitor);
clearInterval(tickerID);
}
/**
* Creates a new promise with a specific result
* @param {*} tt
* @param {*} exitType ("resolve", "reject" or "error")
*/
function prmDelay (tt, exitType) {
return new Promise(function(resolve, reject) {
if( exitType == 'reject' ){
setTimeout(()=>{ reject("REJECTED")}, tt);
} else if( exitType== 'error'){
setTimeout(()=>{ reject(new Error( "ERROR Rejection") ); }, tt);
} else {
setTimeout(()=>{ resolve("RESOLVED") }, tt);
} ;
});
};
run();
person
JohnRC
schedule
20.12.2020
var promiseStatus = NEW_PRIVATE("Promise#status");
,PromiseSet
функцию вSET_PRIVATE(promise, promiseStatus, status);
- person guest271314   schedule 01.06.2015console.log(Promise.new((resolve, reject) => {})
=›Promise { <pending> }
- person Puhlze   schedule 17.05.2019