関数を別の関数に渡し、コールバックとして実行する必要があります。問題は、この関数が時々非同期であるということです:
_async function() {
// Some async actions
}
_
だから私はawait callback()
またはcallback()
を受け取りたい関数のタイプに応じて実行したい。
関数のタイプを知る方法はありますか??
@rndと@estusの両方が正しいです。
しかし、実際の実用的なソリューションで質問に答えるために、あなたは行きます
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*
);
}
これは非常に有効な質問であり、私は誰かが彼に反対票を投じたことに腹を立てています。このタイプのチェックの主な使用例は、ライブラリ/フレームワーク/デコレータです。
これらは初期の段階であり、[〜#〜] valid [〜#〜]の質問に投票するべきではありません。
私はこの簡単な方法を好む:
theFunc.constructor.name == 'AsyncFunction'
NodeJS 10.x以降を使用している場合
ネイティブutil関数 を使用します。
util.types.isAsyncFunction(function foo() {}); // Returns false
util.types.isAsyncFunction(async function foo() {}); // Returns true
ただし、上記の懸念からすべての懸念を念頭に置いてください。偶然に約束を返すだけの関数は、偽陰性を返します。
そしてその上に(ドキュメントから):
これは、JavaScriptエンジンが表示しているもののみを報告することに注意してください。特に、トランスピレーションツールが使用された場合、戻り値は元のソースコードと一致しない場合があります。
ただし、NodeJS 10でasync
を使用し、トランザクションを使用しない場合。これは素晴らしい解決策です。
await
は通常の関数にも使用できるようです。 「良い習慣」とみなすことができるかどうかはわかりませんが、ここにあります:
async function asyncFn() {
// await for some async stuff
return 'hello from asyncFn'
}
function syncFn() {
return 'hello from syncFn'
}
async function run() {
console.log(await asyncFn()) // 'hello from asyncFn'
console.log(await syncFn()) // 'hello from syncFn'
}
run()
短い答え: exposinginstaceof
の後にAsyncFunction
を使用します-以下を参照してください。
長い答え:それをしないでください-以下を参照してください。
関数がasync
キーワードで宣言されたかどうかを検出できます
関数を作成すると、それが関数型であることを示します。
> f1 = function () {};
[Function: f1]
instanceof
演算子でテストできます:
> f1 instanceof Function
true
非同期関数を作成すると、それがAsyncFunction型であることを示します。
> f2 = async function () {}
[AsyncFunction: f2]
したがって、instanceof
でもテストできると期待されるかもしれません。
> f2 instanceof AsyncFunction
ReferenceError: AsyncFunction is not defined
何故ですか? AsyncFunctionはグローバルオブジェクトではないためです。ドキュメントを参照してください:
ご覧のとおり、Reference/Global_Objects
...
AsyncFunction
に簡単にアクセスする必要がある場合は、私のunexposed
モジュールを使用できます。
ローカル変数を取得するには:
const { AsyncFunction } = require('unexposed');
または、グローバルAsyncFunction
を他のグローバルオブジェクトと一緒に追加するには:
require('unexposed').addGlobals();
そして今、上記は期待通りに動作します:
> f2 = async function () {}
[AsyncFunction: f2]
> f2 instanceof AsyncFunction
true
上記のコードは、関数がasync
キーワードで作成されたかどうかをテストしますが、本当に重要なのは、関数の作成方法ではなく、関数がプロミスを返すかどうかです。
この「非同期」機能を使用できるすべての場所:
const f1 = async () => {
// ...
};
これも使用できます:
const f2 = () => new Promise((resolve, reject) => {
});
async
キーワードを使用して作成されていないため、instanceof
または他の回答に投稿された他のメソッドと一致しません。
特に、これを考慮してください:
const f1 = async (x) => {
// ...
};
const f2 = () => f1(123);
f2
はf1
はハードコーディングされた引数であり、async
をここに追加することは、結果がf1
あらゆる点で。
したがって、関数がasync
キーワードを使用して作成されたかどうかを確認することは可能ですが、それをチェックするときに何か間違ったことをしている可能性が高いため、注意して使用してください。
最初はコールバックが約束されていると仮定できます:
export async function runSyncOrAsync(callback: Function) {
let promisOrValue = callback()
if (promisOrValue instanceof Promise) {
promisOrValue = Promise.resolve(promisOrValue)
}
return promisOrValue;
}
あなたのコードでこれを行うことができます:
await runSyncOrAsync(callback)
これにより、コールバックタイプを知らないという問題が解決されます。
ヘイ、
以下は、David Walshが blogpost で提供しているアプローチです。
const isAsync = myFunction.constructor.name === "AsyncFunction";
乾杯!