鍍金池/ 問答/C  Linux  HTML/ forEach中調(diào)用promise 如何控制執(zhí)行順序

forEach中調(diào)用promise 如何控制執(zhí)行順序

最近在做一個網(wǎng)頁爬蟲,先抓取列表頁面,再獲取列表頁所有內(nèi)容頁的url,然后將所有列表頁的url循環(huán)調(diào)用抓取方法,這樣導(dǎo)致抓取的順序不可控,想知道如何能夠控制抓取的順序。
例如:正在抓取A頁面, A頁面抓取完畢;正在抓取B頁面, B頁面抓取完畢...按這樣的順序執(zhí)行。

抓取函數(shù):

function doRequest (url) {
    console.log(chalk.red(`正在抓取 ${url} 的內(nèi)容...`));
    return new Promise ((resolve, reject) => {
        request
        .post(url)
        .set(headers)
        .charset('utf-8')
        .then(result => {
            resolve(result.text);
            console.log(chalk.red(`${url} 的內(nèi)容抓取完畢!`));
        })
        .catch(err => {
            reject(err);
        })
    });
    } 

調(diào)用

// 請求列表
doRequest('list.html')
.then(content => {
    return this.parseList(content); // 得到所有的內(nèi)容頁面地址
})
// 請求內(nèi)容頁
.then(links => {
    return Promise.all(links.map(link => {
        return doRequest(link);
    }))
})
.then (allContent => {
    console.log(allContent);
})

執(zhí)行的結(jié)果

圖片描述

回答
編輯回答
哎呦喂

reduce 然后一直放在then里
https://segmentfault.com/a/11...
看一下應(yīng)用里的 同時請求按序處理 這一塊吧 應(yīng)該是你要的效果

2017年7月8日 03:06
編輯回答
大濕胸

下面是個人的想法,題主可以試一下

let arr = []
// 順序添加抓取頁面 promise 
arr.push(request.post(url).set(headers).charset('utf-8'))  // 抓取第一個頁面
arr.push(request.post(url).set(headers).charset('utf-8'))  // 抓取第二個頁面
arr.push(request.post(url).set(headers).charset('utf-8'))  // 抓取第三個頁面

const handler = () => {
  if (arr.length) {
     let promise = arr.shift();
     promise.then((val) => {
       ......
       console.log(val) // 數(shù)據(jù)處理程序
     }).then(() => {
        // 下一個
        handler()
     })
   }
}

handler()
2018年1月31日 16:22
編輯回答
柚稚

可以直接用 async/await;
要是有一個Promise的隊列會方便很多, 安利一個 promise-queue-plus;

于是基于你的代碼可以這樣寫:

var Queue = require('promise-queue-plus');
var q1 = new Queue(1);  //并發(fā)為1的隊列

// 請求列表
doRequest('list.html')
.then(content => {
    return this.parseList(content); // 得到所有的內(nèi)容頁面地址
})
// 請求內(nèi)容頁
.then(links => {
    return q1.addLikeArray(links,doRequest,{
        "retry":1, //重試次數(shù)
        "timeout":10000  //超時
    },true);
})
.then (allContent => {
    console.log(allContent);
})
2018年1月18日 10:40
編輯回答
舊城人

都放then里可以認(rèn)為你的這段邏輯變成了同步,效率會很低,可以把每個結(jié)果放在數(shù)組的固定位置,用promise.all方法判斷全部加載完再處理要輸出的返回數(shù)組。

2017年1月26日 04:51