(Warning) Turning a Promise Sync, async hoot stack has become corrupted
When turning a Promise into a synchronous Promise
Facing the following error: async hook stack has become corrupted
Error: async hook stack has become corrupted (actual: 6, expected: 7)
1: v8::SnapshotCreator::`default constructor closure'
2: node::CallbackScope::~CallbackScope
3: node::CallbackScope::~CallbackScope
4: RAND_query_egd_bytes
5: RAND_query_egd_bytes
6: uv_timer_get_repeat
7: uv_run
8: 00007FFB97441281
9: 00007FFB974410B6
10: v8::internal::wasm::SignatureMap::Find
11: v8::internal::Builtins::CallableFor
12: v8::internal::Builtins::CallableFor
13: v8::internal::Builtins::CallableFor
14: 000001B9D57043C1
It occures when an error occured during the execution of the Promise. I can reproduce the error:
function waitPromise(val, time) {
let result = undefined;
new Promise(res => {
setTimeout(() => {
throw new Error('whatever');
res(val);
}, time);
}).then(r => {
result = r;
});
while(!result) {
require('deasync').runLoopOnce();
}
return result;
}
console.log(waitPromise('my name is Bond, JAMES BOND!', 2000));
Make sure that in your Promise you do not have any error at all or the error will occur. Solve it by catching all error in the promise and returning the error as the result.
function waitPromise(val, time) {
let result = undefined;
new Promise((res, rej) => {
setTimeout(() => {
try {
throw new Error('whatever');
res(val);
} catch (error) {
rej(error);
}
}, time);
}).then(r => {
result = r;
}).catch(e => {
result = e;
});
while(!result) {
require('deasync').runLoopOnce();
}
return result;
}
console.log(waitPromise('my name is Bond, JAMES BOND!', 2000));
The same error occurs when using deasync-promise.
Following up on this: is there any workaround for this issue to allow the setTimeout to correctly trigger without causing this exception?
As I said:
Solve it by catching all errors in the promise and returning the error as the result.
Instead of rejecting, resolve the error with the object. And process the error outside of the deasync code.
What about something like this?
const promiseSync = deasync((promise, cb) => {
promise.then((result) => cb(null, result)).catch((error) => cb(error));
});
Or does that make the same error?
I'm using it in my .eslintrc.cjs like this:
const deasync = require('deasync'); // powerful magic
const promiseSync = deasync((promise, cb) => {
promise.then((result) => cb(null, result)).catch((error) => cb(error));
});
const importSync = (name) => promiseSync(import(name));
// Look, no await needed here!
const something = importSync('./something.js').default;
module.exports = {
...something,
// ...
}
How about deasync(util.callbackify(promise => promise))?
@NotWearingPants Neat. I didn't know about callbackify. Then my example would become:
const util = require('util')
const deasync = require('deasync')
const promiseSync = deasync(util.callbackify(promise => promise))
const importSync = specifier => promiseSync(import(specifier))
// Look, no await needed here!
const something = importSync('./something.js').default;
module.exports = {
...something,
// ...
}