これは私がfake
データセットを作ってあげる、作品、および非同期データセットからデータを読み込み、fakeAsyncOperation
確認するには。データを密接にモデリングするために、偽のデータセットからの各クエリは、data
とpages
フィールドの応答を返します。
let fake = new Map([
['root', {data: 'root', pages: ['a', 'b', 'c', 'd']}],
['a', {data: 'a', pages: ['a/a', 'a/a']}],
['a/a', {data: 'a/a', pages: []}],
['a/b', {data: 'a/b', pages: ['a/b/a']}],
['a/b/a', {data: 'a/b/a', pages: []}],
['b', {data: 'b', pages: ['b/a']}],
['b/a', {data: 'b/a', pages: ['b/a/a']}],
['b/a/a', {data: 'b/a/a', pages: ['b/a/a/a']}],
['b/a/a/a', {data: 'b/a/a/a', pages: []}],
['c', {data: 'c', pages: ['c/a', 'c/b', 'c/c', 'c/d']}],
['c/a', {data: 'c/a', pages: []}],
['c/b', {data: 'c/b', pages: []}],
['c/c', {data: 'c/c', pages: []}],
['c/d', {data: 'c/d', pages: []}],
['d', {data: 'd', pages: []}]
]);
let fakeAsyncOperation = (page) => {
return new Promise(resolve => {
setTimeout(resolve, 100, fake.get(page))
})
}
次に、お客様のfoo
機能があります。 doo
をenqueue
に変更しました。キューのように機能するためです。これには、累積データを追跡するためのacc
と、キュー内の項目であるxs
(非構造化)の2つのパラメータがあります。
私は新しいasync/await
という構文を使用しました。これは、これに特に対処するのに最適です。プロミスを手作業で作成したり、マニュアルの.then
チェーンを扱う必要はありません。あなたがより多くのことを好きなら、私の読みやすさは、しかし、あなたは簡単にconcat
通話acc.concat([data])
とxs.concat(pages)
のためにこれらを置き換える可能性があるため
私は、再帰呼び出しでスプレッド構文のリベラル利用しました。これは関数型プログラミングなので、好きな不変の操作を選んで使います。
最後に、Promise.all
を使用する他の回答とは異なり、これは各ページをシリーズに処理します。ページが50個のサブページを持つ場合、Promise.all
はパラレルで50個のリクエストを作成しようとしますが、これは望ましくない可能性があります。プログラムを並列から直列に変換することは必ずしも単純ではないので、これがこの答えを提供する理由です。
function foo (page) {
async function enqueue (acc, [x,...xs]) {
if (x === undefined)
return acc
else {
let {data, pages} = await fakeAsyncOperation(x)
return enqueue([...acc, data], [...xs, ...pages])
}
}
return enqueue([], [page])
}
foo('root').then(pages => console.log(pages))
出力
[ 'root',
'a',
'b',
'c',
'd',
'a/a',
'a/a',
'b/a',
'c/a',
'c/b',
'c/c',
'c/d',
'b/a/a',
'b/a/a/a' ]
私は、溶液中のfoo
機能があまりにも遠く、元からではないことを幸せ
備考 - 私はあなたがいることに感謝と思います。彼らは両方ともループのための内部補助機能を使用し、同様の方法で問題にアプローチします。 async/await
はコードをフラットで読みやすく(imo)しています。全体として、これはやや複雑な問題のための優れた解決策だと私は思います。
ああ、約循環参照を忘れないでください。私のデータセットに循環参照はありませんが、ページ'a'
がpages: ['b']
、ページ'b'
がpages: ['a']
の場合、無限再帰が予想されます。この回答はページを連続的に処理するため、これは修正するのが非常に簡単です(累積値acc
に既存のページ識別子をチェックすることによって)。これは、ページを並行して処理するときに処理するのがはるかに手間がかかります(この回答の範囲外です)。
'pages'データで何をしたいですか?あなたは 'if(resp.pages)'ブロックに何も返さず、 'forEach'に渡された関数で使われている戻り値は何もしません。 – Phil
' resp.pages'が真の場合、何も返しません。 'return undefined'を返します。 – Leo