V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a JavaScript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
JavaScript 权威指南第 5 版
Closure: The Definitive Guide
QGabriel
V2EX  ›  JavaScript

promise + settimeout 的问题

  •  
  •   QGabriel · 2021-03-12 17:08:51 +08:00 · 1923 次点击
    这是一个创建于 1381 天前的主题,其中的信息可能已经有所发展或是发生改变。
    let arr = []
    async function foo() {
    return new Promise(async (resolve, reject) => {
    for(let i=0; i< 100; i++){
    (function (i) {
    setTimeout(async ()=> {
    let a = await xxx(i)
    arr.push(a)
    }, 1000 * i * 5)
    })(i)
    }
    A => setTimeout(resolve, 10000, arr)
    })

    }

    B => foo().then(res=> {
    ...
    })


    遍历个数组调接口,接口限制 1 分钟最多只能调 20 次.

    怎么能让这段代码改成同步执行,等待遍历完成后 我在 A 那不用写等待时间
    B 直接获取到 arr 的数据
    14 条回复    2021-03-16 09:02:29 +08:00
    chairuosen
        1
    chairuosen  
       2021-03-12 17:13:35 +08:00
    for 里可以 await,for 结束后直接 resolve,当然,上下文得在 async 里
    QGabriel
        2
    QGabriel  
    OP
       2021-03-12 17:23:28 +08:00
    @chairuosen 现在不就是 for 里 await 吗
    chairuosen
        3
    chairuosen  
       2021-03-12 17:35:24 +08:00
    @QGabriel #2 不是,套了一个普通 function,一个 setTimeout 啊
    QGabriel
        4
    QGabriel  
    OP
       2021-03-12 17:36:34 +08:00
    @chairuosen 没懂你什么意思
    yunyuyuan
        5
    yunyuyuan  
       2021-03-12 17:49:10 +08:00
    ```javascript
    const arr = []
    const reqList = []
    // just for test
    async function sleep (sec){
    return new Promise(resolve => {
    setTimeout(()=>{
    resolve()
    }, sec)
    })
    }

    async function foo() {
    return new Promise(async (resolve, reject) => {
    for(let i=0; i< 5; i++){
    (function (i) {
    reqList.push(new Promise(resolve1 => {
    const func = async ()=> {
    let a = await sleep(5)
    arr.push(a)
    console.log(`${i} ok`)
    resolve1()
    }
    setTimeout(func, 1000 * i )
    }))
    })(i)
    }
    Promise.all(reqList).then(()=>{
    console.log('all ok')
    resolve()
    })
    })
    }

    foo().then(res=> {
    })
    ```
    yunyuyuan
        6
    yunyuyuan  
       2021-03-12 17:49:51 +08:00
    没缩进是真的难受
    beginor
        7
    beginor  
       2021-03-12 18:37:43 +08:00 via Android
    没缩进看着不难受么?
    wednesdayco
        8
    wednesdayco  
       2021-03-12 19:09:47 +08:00
    这不是标准面试题里面的 EventLoop 问题么
    leelz
        9
    leelz  
       2021-03-13 08:25:25 +08:00
    都 let 了 还用什么 iife
    ljpCN
        10
    ljpCN  
       2021-03-13 16:43:17 +08:00
    一分钟调 20 次,是指每调得等 3 秒,还是单纯的 60 秒内不超过 20 就行?如果是后者,那么周期是从哪里开始算呢?比如,第一分钟的最后一秒连续调了 20 次,第二分钟的第一秒连续调了 20 次,但只看这两秒的话,两秒钟就有了 40 次,这种情况符合你说的一分钟 20 次吗?
    ljpCN
        11
    ljpCN  
       2021-03-13 16:55:19 +08:00
    没有时间限制的版本(其实用 Promise.all 让它并发就行,但这里为了写法一致就写成了同步):
    https://imgtu.com/i/6djJ0g
    三秒钟只能请求一次(搞一个 setTimeout 一起让 Promise.all 等,两者必须都 resolve 一次循环才结束):
    https://imgtu.com/i/6djGnS
    ljpCN
        12
    ljpCN  
       2021-03-13 16:55:45 +08:00
    ljpCN
        13
    ljpCN  
       2021-03-13 17:01:59 +08:00
    QGabriel
        14
    QGabriel  
    OP
       2021-03-16 09:02:29 +08:00
    @ljpCN 感谢老哥
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3587 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 00:56 · PVG 08:56 · LAX 16:56 · JFK 19:56
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.