どのバージョンの非同期を使用していますか?
3.1.0
どの環境で問題が発生しましたか(ノードバージョン/ブラウザバージョン)
ノード12.9.1、npm 6.10.2、ブラウザN / A
あなたは何をした?
問題にはstackoverflowにスレッドがあります
https://stackoverflow.com/questions/57622495/async-maplimit-with-promise/57659221#57659221
基本的に、私はこのコードを持っています:
async = require('async');
let numPromise = async.mapLimit(['1','2','3','4','5'], 3, function(num, callback){
setTimeout(function(){
num = num * 2,
console.log(num);
callback(null, num);
},
2000);
})
numPromise
.then((result) => console.log("success:" + result))
.catch(() => console.log("no success"));
何が起こると思いましたか?
エラーなしで実行します。「numPromise」にはPromiseが含まれている必要があります。 コンソールは「2,4,6,8,10」および「 success: 2,4,6,8,10」をログに記録する必要があります
実際の結果はどうでしたか?
エラーをスローします:TypeError: undefinedのプロパティ 'then'を読み取ることができません
注:「async」の代わりに「promise-async」モジュールを使用すると、このコードは適切に機能します。 ドキュメントによると、コールバックが提供されていない場合、async.mapLimit(およびその他)はPromiseを返しますが、未定義になります。 まだ動作するサンプルが見つかりませんでした(「サンプルが必要」の問題に関する私の提案も参照してください)。
const async = require('async');
const delay = require('util').promisify(setTimeout);
const numPromise = async.mapLimit(['1','2','3','4','5'], 3, async num => delay(200).then(() => num*2))
// or const numPromise = async.mapLimit(['1','2','3','4','5'], 3, async num => {
// await delay(200);
// return num*2;
// })
numPromise.then(console.log)
たくさんの、合理的な例。 残念ながら、「SyntaxError:awaitはasync関数でのみ有効です」( 'await async.mapLimit'の場合)
他に考慮しなければならないことはありますか?
エラーメッセージはすべてを示しています。awaitは、トップレベルのawaitプロポーザルが実装されるまで、非同期関数でのみ有効です。
イップは、完全に機能する例を探していました。これは本当に私が苦労した部分だからです。 でも気にしないでください、ついにそれを立ち上げて実行しました:
const myAsyncFunction = async function(){
//const numPromise = await async.mapLimit(['1','2','3','4','5'], 3, async num => delay(200).then(() => num*2))
const numPromise = await async.mapLimit(['1','2','3','4','5'], 3, async num => {
await delay(2000);
console.log(num*2);
return num*2;
})
//numPromise.then(console.log)
return numPromise;
}
myAsyncFunction()
.then((result) => console.log(result));
以前の試みと何が違うのかはまだよくわかりませんが、これについて検証し、さらに結論を追加します。
いずれにせよ、私のポイントは、これはすべて完全に直感的ではないということです。したがって、このような例が役立つと思います。
そして... async.mapLimitがそれ自体でプレーンなPromiseを返す必要があるのに、なぜすべてのasync / awaitsをラップする必要があるのかまだ完全には理解していません...
おっと、編集した前のコードで待つのを忘れました
了解しました。完全に確認しました:-)おそらく主な問題は、iteratee関数が完全に非同期ではなかったことでしたか?
とにかく、これは見た目が魅力のように機能し、おそらく素晴らしい例でもあります! 私と一緒にこれを続けてくれてありがとう!
理由については、 https://github.com/caolan/async/issues/1673を参照して
async.mapLimit(['1','2','3','4','5'], 3, async num => delay(200).then(() => num*2)) // works
async.mapLimit(['1','2','3','4','5'], 3, num => delay(200).then(() => num*2)) // doesn't work
Promise.all(['1','2','3','4','5'].map(num => delay(200).then(() => num*2))) // works (plain promises)
なるほど、あなたは完全に私と一緒です、つまり同じ問題を抱えていました。
私の主なポイントは本当に次のとおりだと思います-ドキュメントには「リターン:コールバックが渡されない場合の約束」と記載されています-したがって、コールバックバリアントがあり、それを省略した場合、どうすれば必要だと思うようになりますかコールバックバージョンでそれなしで機能したときに「async」キーワードを追加します。 さらに、「promise-async」モジュールを使用すると、期待どおりに機能します。
さらに、上記の「Promise.all」の例が機能する理由をまだ理解していません...これは私にとって本当に混乱しています。
iteratee関数がasync
か、コールバックを使用しても、最後のコールバックが省略された場合でも、promiseの返送に影響はありません。 これはバグです。
これは#1685に関連していると思います
これは#1685に関連していると思います
私のコードサンプルのいくつかのバージョンでも、以前にその問題が発生したことを間違いなく覚えています。 私は明らかにそれがいくつかの間違ったコーディングによって引き起こされたと思いました。 だから、それが別のフレーバーでも表示されるのを見るのは興味深いです。
私はこれをもっと調べました。
mapLimit
は意図したとおりに機能しています。 ここで人々が目にする問題は、promiseを返す関数の検出の制限、またはasync
関数を保持しないコンパイラ(babel、typescriptなど)が原因であると賭けます。
私はこれをもっと調べました。
mapLimit
は意図したとおりに機能しています。 ここで人々が目にする問題は、promiseを返す関数の検出の制限、またはasync
関数を保持しないコンパイラ(babel、typescriptなど)が原因であると賭けます。
async
がコンパイルで保持されないようなシナリオを処理する最良の方法は何ですか?
async
関数をasyncify
ラップします。 http://caolan.github.io/async/v3/global.html#AsyncFunction
最も参考になるコメント