部屋の中の象の1つは、NodeとChromeに導入された新しいasync
/ await
のサポートであり、まもなく他のすべての主要なブラウザーにヒットします。 私はAsyncがasync
/ await
の世界で何ができるかを考えてきました。
現在、 asyncify
でラップすることにより、 async
関数を適応させることができます。 async
関数は基本的にPromiseを返す関数であるため、その古いアダプターはそれをコールバックスタイルの関数に簡単に変換できます。 しかし、それはややばかげた見た目になります:
async.mapLimit(arr, 10, async.asyncify(async (val) => {
let foo = await doSomething(val);
//...
return bar;
}), done);
ただし、 async
関数の仕様の機能の1つは、次のとおりです。
Object.getPrototypeOf(asyncFn)[Symbol.toStringTag] === "AsyncFunction"
これにより、(ネイティブの) async
関数を簡単に検出できます。 この手法を使用して、それらを自動的にasyncify
することができます。 上記の例は次のようになります。
async.mapLimit(arr, 10, async (val) => {
let foo = await doSomething(val);
//...
return bar;
}, done);
...これははるかに自然に流れるようです。 また、コールバックを引き続き使用する必要があると思います。 ユーザーが結果をawait
したい場合は、関数をpromisify
にするか、全体としてpify
非同期にする必要があります。
let result = await pify(async.mapLimit)(arr, 10, async (val) => {
let foo = await doSomething(val);
//...
return bar;
});
async
関数を検出するための上記の方法は、ネイティブ関数でのみ機能します。 Babelのトランスパイルされた関数を検出する方法はないと思います。 コールバックをさかのぼって渡さないようにする必要があるため、Promisesを返すだけの通常の関数を確実に検出することはできません。 これは非常に近代的な環境ではトランスパイラーなしでのみ機能するという大きな警告があります。そうでない場合は、手動でasyncify
でラップする必要があります。
また、確かに、多くの非同期メソッドはasync
/ await
では意味がありません。 ほとんどの制御フローメソッド( auto
やqueue
などを除く)は、ネイティブの制御フロー構造を使用すると、より簡単に複製できます。 map
とparallel
は、 Promise.map
とPromise.all
に置き換えることができます。 ただし、コレクションの制限関数は、 auto
やその他のいくつかの関数と同様に非常に便利です。 (また、$ async
関数を使用したautoInject
は、非同期制御フローの夢です!)
これについてもう少し考えてみますが、これがどのように見えるかをよりよく想像できるように、いくつかの技術的な質問をしたいと思います。
Object.getPrototypeOf(asyncFn)[Symbol.toStringTag] === "AsyncFunction"
を実行する理由はありますか、それともasyncFn[Symbol.toStringTag] === "AsyncFunction"
を実行できますか(FFで機能するようです)?
誰かがcb(err, arg)
の形式のコールバックを提供するときはいつでも、それがAsyncFunction
であるかどうかを検出する必要があるという提案です。 非同期関数の場合はpromisify
を適用する必要があり、それ以外の場合はそのまま使用します
また、申し訳ありませんが、awaitの例には従いません。関数がAsyncFunction
であることが検出された場合、 await
をサポートする際の課題は何ですか?
Object.getPrototypeOf(asyncFn)[Symbol.toStringTag] === "AsyncFunction"
を実行する理由はありますか、それともasyncFn[Symbol.toStringTag] === "AsyncFunction"
を実行できますか(FFで機能するようです)?
これは、ECMA仕様の標準的な方法です。 理論的には、誰かがasyncFn[Symbol.toStringTag]
を上書きする可能性があると思います。
したがって、誰かがcb(err、arg)形式のコールバックを提供するときはいつでも、それがAsyncFunctionであるかどうかを検出する必要があるという提案です。 非同期関数の場合はpromisifyを適用する必要があり、それ以外の場合はそのまま使用します
少し後ろ向きだと思います。 コールバックを受け入れるiteratee関数( function(args..., callback) {}
)を受け入れる場合は常に、それがasync
関数であるかどうかを確認してから、 asyncify
にする必要があります。
await
の例は、Asyncメソッドをawait
したい場合に、誰かが行うことです。 Asyncメソッドがpromiseを返し始めて、それが機能するようにするべきではないと思います。ユーザーに任せてください。
#1390で実装されました!
これは重大な変更であり、デプロイされたコードを破壊しました。 メジャーバージョンを増やさずにそういうことをするときはよく考えてください。
PS:このライブラリで行っているすべての素晴らしい作業に感謝します😄
シュート! 何が壊れたのか。 詳細を記載したチケットを作成していただけませんか
これが機能しなかった環境?
ありがとう!
2017年4月5日水曜日午前10時18分マニュエルヴァルスフェルナンデス<
[email protected]>は次のように書いています:
これは重大な変更であり、デプロイされたコードを破壊しました。 よく考えてください
メジャーバージョンを増やさずにそのようなことをするとき。PS:このライブラリで行っているすべての素晴らしい作業に感謝します😄
—
コメントしたのでこれを受け取っています。
このメールに直接返信し、GitHubで表示してください
https://github.com/caolan/async/issues/1386#issuecomment-291875817 、またはミュート
スレッド
https://github.com/notifications/unsubscribe-auth/ADUIEPNkTSOVuuiwucBVrH983X6B568Wks5rs6K3gaJpZM4Mf64R
。
同意しました、それは私のビルドも壊しました...
数日前に機能していた非同期関数を呼び出していたウォーターフォールは、非同期コールバックが関数に提供されなくなったため、「cb isnotfunction」で失敗し始めました。
申し訳ありませんが、コードが壊れました。 async
関数のユースケースは予想していませんでした。 コールバックを使用するのではなく、2.2.0にロールバックするか、コードを必要な値にリファクタリングすることをお勧めしreturn
。 残念ながら、猫はこの機能で袋から出されているので、ロールバックすることはできません。
@aearlyお願いします、言わないでください!! :1st_place_medalに答えてくれて本当にうれしいです:
@manvallsは、ロールバックする必要のない優れたソリューションを教えてくれました。 シンボルを使用して関数宣言のasync
を検出しているときに、彼は検出をだますための賢い方法を考えました。
私のウォーターフォールは他のモジュールからエクスポートされた関数を使用していましたが、そのうちの1つはasync
であり、失敗の原因でした。
したがって、次のように変更するだけです。
...
/* services module */
function doThis(param, cb) {
...
}
async function doThatAsync(param, cb) {
...
}
module.exports = {
doThis: doThis,
doThat: doThatAsync
};
...
async.waterfall([
services.doThis,
services.doThat, // fails with "cb is not a function"
], err => {
...
}
に:
...
/* services module */
function doThis(param, cb) {
...
}
async function doThatAsync(param, cb) {
...
}
module.exports = {
doThis: doThis,
doThat: (...args) => doThatAsync(..args) // cheating the detection
};
...
async.waterfall([
services.doThis,
services.doThat, /* it works!!! */
], err => {
...
}
どうもありがとうございました
async.autoInject()でasync / awaitを使用できますか?
async.autoInject({
conn1: async function () {
return conn1;
},
conn2: async function () {
return conn2;
},
});
うまくいかないようです、私は得ます:
エラー:autoInjectタスク関数には明示的なパラメーターが必要です。
/Users/alexamil/WebstormProjects/nabisco/cdt-now/node_modules/async/dist/async.js:2081:23
/ Users / alexamil / WebstormProjects / nabisco / cdt-now / node_modules / asyncにあります
@ORESoftwareはい、 async
関数はautoInject
で動作するはずです。 Chromeに投稿したコードをテストしたところ、実行されました。 conn1
とconn2
はundefined
$であるため、最後のコールバックでReferenceError
を受け取りました。 に変更した後
async.autoInject({
conn1: async function () {
return 'foo'
},
conn2: async function () {
return 'bar'
},
})
それはうまくいきます。 ただし、トランスパイルされasync
関数はサポートされていません。 コードをトランスパイルしていますか?
最も参考になるコメント
これは、ECMA仕様の標準的な方法です。 理論的には、誰かが
asyncFn[Symbol.toStringTag]
を上書きする可能性があると思います。少し後ろ向きだと思います。 コールバックを受け入れるiteratee関数(
function(args..., callback) {}
)を受け入れる場合は常に、それがasync
関数であるかどうかを確認してから、asyncify
にする必要があります。await
の例は、Asyncメソッドをawait
したい場合に、誰かが行うことです。 Asyncメソッドがpromiseを返し始めて、それが機能するようにするべきではないと思います。ユーザーに任せてください。