forEach 中调用 promise 如何控制执行顺序? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
yuuk
V2EX    Node.js

forEach 中调用 promise 如何控制执行顺序?

  •  1
     
  •   yuuk 2018-05-04 23:34:46 +08:00 8887 次点击
    这是一个创建于 2718 天前的主题,其中的信息可能已经有所发展或是发生改变。

    最近在做一个网页爬虫,先抓取列表页面,再获取列表页所有内容页的 url,然后将所有列表页的 url 循环调用抓取方法,这样导致抓取的顺序不可控,想知道如何能够控制抓取的顺序。 例如:正在抓取 A 页面, A 页面抓取完毕;正在抓取 B 页面, B 页面抓取完毕...按这样的顺序执行。

    抓取函数:

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

    调用

    // 请求列表 doRequest('list.html') .then(cOntent=> { return this.parseList(content); // 得到所有的内容页面地址 }) // 请求内容页 .then(links => { return Promise.all(links.map(link => { return doRequest(link); })) }) .then (allCOntent=> { console.log(allContent); }) 

    执行的结果

    图片描述

    这个结果不是按照顺序来的。

    23 条回复    2018-05-05 14:24:38 +08:00
    soooon
        1
    soooon  
       2018-05-04 23:45:54 +08:00
    用 async 模块串行执行吧: https://github.com/caolan/async
    ashong
        2
    ashong  
       2018-05-04 23:48:27 +08:00
    array.reduce
    xudaiqing
        3
    xudaiqing  
       2018-05-04 23:56:06 +08:00
    Bluebird 的 Promise.each
    或者手动拼接 then
    ashong
        4
    ashong  
       2018-05-05 00:07:52 +08:00
    links.reduce( (promise, link) => { return promise.then( ()=>{
    // do request with link
    }) }, Promise.resolve()).then( () =>{
    // done
    })
    yuuk
        5
    yuuk  
    OP
       2018-05-05 00:26:51 +08:00
    @ashong 这个也只是将所有的请求结果一次性范围。并没有保证顺序~
    IvanLi127
        6
    IvanLi127  
       2018-05-05 00:48:55 +08:00 via Android
    等待上一个执行完成,再执行下一个。await 了解一下?话说回来,你为啥要顺序执行?
    df4VW
        7
    df4VW  
       2018-05-05 00:52:05 +08:00
    1 楼都已经回答你喽
    ashong
        8
    ashong  
       2018-05-05 00:53:25 +08:00
    @yuuk520 确定是保证顺序的
    dd0754
        9
    dd0754  
       2018-05-05 01:14:33 +08:00
    加个字段来排序不是更好?页面多了你也一个一个爬啊?
    ETiV
        10
    ETiV  
       2018-05-05 01:17:36 +08:00 via iPhone
    bluebird +1
    des
        11
    des  
       2018-05-05 02:15:06 +08:00 via Android
    没人说正经的 for of ???
    des
        12
    des  
       2018-05-05 02:18:00 +08:00 via Android
    @des async + for of 完美解决,反正后端 node 不像前端不能控制版本
    yimity
        13
    yimity  
       2018-05-05 08:21:18 +08:00 via Android
    all 中,你给的数组的顺序是什么,最终结果就是什么顺序,但是不保证拿到结果的过程的顺序。
    yuuk
        14
    yuuk  
    OP
       2018-05-05 10:20:16 +08:00
    @des 大佬,有 demo 么~
    des
        15
    des  
       2018-05-05 10:46:04 +08:00 via Android
    @yuuk520
    (async function() {
    // 请求列表
    comst links = await doRequest('list.html').then(cOntent=> {
    return this.parseList(content); // 得到所有的内容页面地址
    });
    for (const link of links) {
    // 请求内容页
    const allCOntent= await doRequest(link);
    console.log(allContent);
    }
    })()
    yuuk
        16
    yuuk  
    OP
       2018-05-05 11:00:50 +08:00
    @des 厉害!!!这样可以实现,顺便有个疑问想请教一下

    doRequest('list.html').then(cOntent=> {
    return parseList(content);
    }).then(links => {
    links.forEach(async function(link){
    const allCOntent= await doRequest(link);
    });
    })

    这样为啥就不行呢~
    yuuk
        17
    yuuk  
    OP
       2018-05-05 11:05:30 +08:00
    @yuuk520 明白了。。。需要这样写

    doRequest('list.html').then(cOntent=> {
    return parseList(content);
    }).then(async function(links){
    for (const link of links) {
    const allCOntent= await doRequest(link);
    }
    })
    yuuk
        18
    yuuk  
    OP
       2018-05-05 11:05:56 +08:00
    感谢各位的帮助,谢谢大家。
    ChefIsAwesome
        19
    ChefIsAwesome  
       2018-05-05 11:33:25 +08:00 via Android
    你可以自己再琢磨下怎么实现一次抓几个,这几个结束后再执行后面几个。一个一个抓太慢了。
    POPOEVER
        20
    POPOEVER  
       2018-05-05 12:28:01 +08:00
    基于 express/koa 的话为什么不用中间件?
    mrcode
        21
    mrcode  
       2018-05-05 13:53:48 +08:00
    同 #11,使用 for-of 循环解决
    orzfly
        22
    orzfly  
       2018-05-05 14:23:44 +08:00 via Android   1
    Bluebird.mapSeries(...)
    Bluebird.map(..., { concurrency: 5 })
    orzfly
        23
    orzfly  
       2018-05-05 14:24:38 +08:00 via Android
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5864 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 29ms UTC 03:22 PVG 11:22 LAX 20:22 JFK 23:22
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86