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

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

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

// 請(qǐng)求列表
doRequest('list.html')
.then(content => {
    return this.parseList(content); // 得到所有的內(nèi)容頁(yè)面地址
})
// 請(qǐng)求內(nèi)容頁(yè)
.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)用里的 同時(shí)請(qǐng)求按序處理 這一塊吧 應(yīng)該是你要的效果

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

下面是個(gè)人的想法,題主可以試一下

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

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

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

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

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

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

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

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

2017年1月26日 04:51