so.
First, a sample code that detects a promis or an asynchronous function, in which case time and result null .
Please pay attention to two blocks:
#region проверка на страрте#region проверка в процессе
void function() { /** * @param _f функция */ let test = (_f) => { //#region проверка на страрте if (!_f || !(_f instanceof Function)) throw new TypeError('!_f of _f not Function') // -- // if (_f[Symbol.toStringTag] === 'AsyncFunction') throw new TypeError('AsyncFunction') // -- // const AsyncFunction = (async () => {}).constructor; // if (_f instanceof AsyncFunction) throw new TypeError('AsyncFunction') // -- //#endregion проверка на страрте let isPromiseOrAsync = (_f) => (_f == Promise.resolve(_f)) //проверка в процессе let result = null // результат выполнения функции let time = null // время выполнения try { time = performance.now() // засекаем время result = _f() // вызоваем тестируемую функциию time = performance.now() - time // вычисляем время //#region проверка в процессе if (isPromiseOrAsync(result)) { result = null throw new TypeError('PromiseOrAsync') } //#endregion проверка в процессе } catch (_e) { time = null console.log(_e) } return [time, result] } function foo() { return 'res' } async function bar() { return 'res' } function baz() { return Promise.resolve('res') } console.log('foo', test(foo)) //foo (2) [0, "res"] //TypeError: PromiseOrAsync console.log('bar', test(bar)) //bar (2) [null, null] //TypeError: PromiseOrAsync console.log('baz', test(baz)) //baz (2) [null, null] }()
#region проверка на страрте
Of course, it is preferable to perform TypeError detection at the very beginning of the function, and in the case of asynchronous functions this is possible, not in the case of promise.
asynchronous function detection
I will give two examples taken from stackoverflow.com
first example:
if (_f[Symbol.toStringTag] === 'AsyncFunction') throw new TypeError('AsyncFunction')
second example:
const AsyncFunction = (async () => {}).constructor; if (_f instanceof AsyncFunction) throw new TypeError('AsyncFunction')
and one from here at stackoverflow.com
function isAsync (func) { const string = func.toString().trim(); return !!( // native string.match(/^async /) || // babel (this may change, but hey...) string.match(/return _ref[^\.]*\.apply/) // insert your other dirty transpiler check // there are other more complex situations that maybe require you to check the return line for a *promise* ); }
promise detection
- out of
#region проверка в процессе
And so, let's talk about promises, and what is a 'check in process'
what is a 'check in process'
look, there is a baz function
function baz() { return Promise.resolve('res') }
it is a function, just a function, the most ordinary
but she returns promis
but we will not know about it until we call it (we do not take into account the third example given earlier)
void function() { function baz() { return Promise.resolve('res') } let p = baz() console.log('baz', p instanceof Promise) //baz true console.log('baz', p.then !== void 0) //baz true //<---категорически не рекомендую async function bar() { return 'res' } let a = bar() console.log('bar', a instanceof Promise) //bar true console.log('bar', a.then !== void 0) //bar true let isPromiseOrAsync = (_o) => (_o == Promise.resolve(_o)) //проверка в процессе console.log('baz', isPromiseOrAsync(p)) //baz true console.log('bar', isPromiseOrAsync(a)) //bar true }()
I personally liked the isPromiseOrAsync method peeking here source . The author of the answer refers to the specs, gives proofs and complains about the instanceof method and safari.