こんにちは
javascript
1urls.forEach((url)=>{
2 getTitle(url);
3});
とすることで、urls
の先頭から順に getTitle(url)
が実行されますが、だからといって、各URLに対するHTTP(S)リクエストの返信が、リクエストした順に返ってくるとは限りません。urls
に入っている順で結果も得たいのであれば、すべてのリクエストに対するレスポンスが返ってきてから、それぞれの結果を、urls
に入っている順を保って得る必要がありますが、これを実現する方法として、
を使うことが考えられます。すなわち、各リクエストをPromise にして、 すべてのリクエストが返ってきてから、urls
の要素の順に、各レスポンスから取得した結果を表示するという制御を Promise.all で行います。
以下、そのコード例です。
javascript
1'use strict';
2const request = require('request');
3const { JSDOM } = require('jsdom');
4
5const urls = [];
6urls.push("https://www.example.com/xxxxxxx");
7urls.push("https://www.example.com/xxxxxxx/eapg/2");
8urls.push("https://www.example.com/hogehoge");
9urls.push("https://www.example.com/hogehoge/eapg/2");
10urls.push("https://www.example.com/hogehoge/eapg/3");
11urls.push("https://www.example.com/hogehoge/eapg/4");
12urls.push("https://www.example.com/hogehoge/eapg/5");
13urls.push("https://www.example.com/hogehoge/eapg/6");
14urls.push("https://www.example.com/hogehoge/eapg/7");
15urls.push("https://www.example.com/hogehoge/eapg/8");
16urls.push("https://www.example.com/hogehoge/eapg/9");
17
18Promise
19 .all(urls.map(url => printTitle(url)))
20 .then(results => {
21 results.forEach(({ url, aList }) => {
22 console.log(url);
23 console.log([...aList].map(a => `\t${a.textContent}`).join('\n'));
24 })
25 }).catch(e => {
26 console.error(e);
27 })
28
29function printTitle(url) {
30 return new Promise((resolve, reject) => {
31 request(url, (e, response, body) => {
32 if (e) reject(e);
33 try {
34 const dom = new JSDOM(body);
35 const selector = "#primary > div > div > div > article > header > h2 > a";
36 const aList = dom.window.document.querySelectorAll(selector);
37 resolve({ url, aList });
38 } catch (e2) {
39 reject(e2);
40 }
41 });
42 });
43}
44
なお上記では、ご質問にある GitHubレポジトリにあるコードをもとに修正しており、各URLを差し障りのないものに変えています。
以上、参考になれば幸いです。
追記
request のドキュメント を眺めていましたら、これを作っている同じチームで、Promiseでラップしたものも提供しているとの一節がありました。その提供されているものの中の request/request-promise を使うと、以下のような感じで、もっと短く書けそうです。
javascript
1'use strict';
2const rp = require('request-promise');
3const {
4 JSDOM
5} = require('jsdom');
6
7const urls = [];
8urls.push("https://www.example.com/xxxxxxx");
9urls.push("https://www.example.com/xxxxxxx/eapg/2");
10urls.push("https://www.example.com/hogehoge");
11urls.push("https://www.example.com/hogehoge/eapg/2");
12urls.push("https://www.example.com/hogehoge/eapg/3");
13urls.push("https://www.example.com/hogehoge/eapg/4");
14urls.push("https://www.example.com/hogehoge/eapg/5");
15urls.push("https://www.example.com/hogehoge/eapg/6");
16urls.push("https://www.example.com/hogehoge/eapg/7");
17urls.push("https://www.example.com/hogehoge/eapg/8");
18urls.push("https://www.example.com/hogehoge/eapg/9");
19
20const selector = "#primary > div > div > div > article > header > h2 > a";
21
22Promise
23 .all(urls.map(url => rp(url)))
24 .then(htmls => {
25 htmls.forEach((html, i) => {
26 console.log(urls[i]);
27
28 const dom = new JSDOM(html);
29 const aList = dom.window.document.querySelectorAll(selector);
30 console.log([...aList].map(a => `\t${a.textContent}`).join('\n'));
31 })
32 }).catch(e => {
33 console.error(e);
34 });