2016-03-29 17 views
0

次の関数は、リンクの配列を受け取り、リモートWebサイトをスキャンし、async.waterfallを使用して1ページあたり10個のブログ投稿を取得し、次にそれぞれのブログ投稿用のコメントを取得します。ネストされたasync.eachSeriesスタックの反復

// @param {Array} url 
export default function getData(url, cb) { 
    const arrayOfPosts = []; 
    // Outer loop 
    async.eachSeries(url, (link, topLVLcb) => { 

    // Waterfall 
    async.waterfall([ 

     // Collects links to posts 
     callback => { 
     request(link, (err, response, body) => { 
      console.log(`working on ${link}`); 

      const $ = cheerio.load(body); 

      // OVERALL 10 LINKS PER ONE BLOGPOST 
      $('.blogpost').each((i, element) => { 

      // build post ojbect 

      const post = { 
       content, 
       link, 
       comments: [] 
      } 
      arrayOfPosts.push(post); 
      }); 
      callback(null, arrayOfPosts); 
     }); 
     }, 

     // Looks for details in given post 
     (arrOfPosts, postDetailsCallback) => { 
     let counter = 1; 

     // Inner loop through 10 links 
     async.eachSeries(arrOfPosts, (post, eachSeriesCallback) => { 
      request(post.link, (err, response, body) => { 
      console.log(counter++); 
      const $ = cheerio.load(body); 
      $('.comment').each((i, element) => { 

       // build comment 

       const comment = { 
       author, 
       content 
       }; 

       post.comments.push(comment); 
      }); 
      eachSeriesCallback(null); 
      }); 
     }, postDetailsCallback); 
     } 
    ], err => { 
     console.log('DONE PAGE'); 
     console.log('*************************'); 
     topLVLcb(err); 
    }); 
    }, (result, err) => { 
    if (err) { 
     throw err; 
    } else { 
     console.log('DONE ALL'); 
     cb(arrayOfPosts); 
    } 
    }); 
} 

それは、このような出力を提供します:

working on www.mywebsite.com/ 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
DONE PAGE 
************************************************************** 
working on www.mywebsite.com/posts/1 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
DONE PAGE 
************************************************************** 

そして、それは、各反復でもう一度起動、10で各ページをインクリメントします。一方、各ページを10回スキャンする必要があります。私はコールバックのいくつかを混乱させたと思うが、私は正確に何時間も把握できない。これは私の最初のnodejs非同期コードであり、非常に圧倒的です。

+0

あなたの間違いだこと2番目のline.const arrayOfPostsはグローバルであり、繰り返しごとに0,10,20,30,40,50、...となります! – vkstack

答えて

1

トップレベルarrayOfPostsのすべての投稿を保存しているようですが、それは2番目のウォーターフォール機能では、コールバックに渡しているので、最初からすべての投稿を処理することになります。したがって、投稿へのリンクを収集する最初のコールバックでは、次のコールバックに渡すポストのローカル配列が必要です。

+0

ありがとう、それはそのようなマイナーな詳細があなたを最も混乱させる何か。 –

1

arrayOfPost[]あなたは は、次のようにのような新しいarrayOfPost[]を作成する必要がありurlの各 URL要素のために...すべてのasync.waterfallにグローバルである....

export default function getData(url, cb) { 
    const arrayOfPosts = []; 
    // Outer loop 
    async.eachSeries(url, (link, topLVLcb) => { 
     var tmpArr=[]; 
    // Waterfall 
    async.waterfall([ 

     // Collects links to posts 
     callback => { 
     request(link, (err, response, body) => { 
     console.log(`working on ${link}`); 

    const $ = cheerio.load(body); 

    // OVERALL 10 LINKS PER ONE BLOGPOST 
    $('.blogpost').each((i, element) => { 

     // build post ojbect 

     const post = { 
      content, 
      link, 
      comments: [] 
     } 
     tmpArr.push(post); 
     arrayOfPosts.push(post); 
}); 
    callback(null, tmpArr);//this tmpArr which is being passed will always cantain 10 items(posts) so there will be 10 iterations for each element in url 
}); 
}, 

    // Looks for details in given post 
    (arrOfPosts, postDetailsCallback) => { 
     let counter = 1; 

     // Inner loop through 10 links 
     async.eachSeries(arrOfPosts, (post, eachSeriesCallback) => { 
      request(post.link, (err, response, body) => { 
      console.log(counter++); 
      const $ = cheerio.load(body); 
      $('.comment').each((i, element) => { 

       // build comment 

       const comment = { 
        author, 
        content 
       }; 

      post.comments.push(comment); 
     }); 
      eachSeriesCallback(null); 
     }); 
    }, postDetailsCallback); 
    } 
    ], err => { 
     console.log('DONE PAGE'); 
     console.log('*************************'); 
     topLVLcb(err); 
    }); 
}, (result, err) => { 
     if (err) { 
      throw err; 
     } else { 
      console.log('DONE ALL'); 
      cb(arrayOfPosts); 
     } 
    }); 
} 
+0

答えをありがとう、このコードは動作しません。なぜなら、最下位の 'cb'は配列がこの関数から抽出することを期待しているからです。 –

+0

更新されました。 – vkstack

関連する問題