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

如何用 js 优雅的在前端实现循环多次向后端的 ajax 请求,且这些 ajax 是按顺序发起的

  •  
  •   abcbuzhiming · 2017-04-06 21:29:24 +08:00 · 11439 次点击
    这是一个创建于 2577 天前的主题,其中的信息可能已经有所发展或是发生改变。
    我现在有个这样的需求,前端页面要循环向服务器发起请求,一个请求结束后再发起下一次,直到循环条件结束。为的是缩短服务器每次处理数据时间,并及时的让客户端逐步看到处理结果,以前用 jquery 做,无非就两个方案: 1.aysnc 改成 false 变成同步请求, 2.递归调用,非常丑陋。现在弃用了 jquery ,用的 axios,这个库没法进行同步请求。那该怎么办,只有递归一条路了吗?
    24 条回复    2017-04-07 16:49:11 +08:00
    ChefIsAwesome
        1
    ChefIsAwesome  
       2017-04-06 21:45:54 +08:00 via Android
    只能递归啊。丑不丑还不是看你写法
    murmur
        2
    murmur  
       2017-04-06 21:47:18 +08:00
    axios 本身基于 promise 你怎么让他同步 加了 async 写的好看但是还是要 babel
    所以最简单的办法还是一开始就用 promise
    kindjeff
        3
    kindjeff  
       2017-04-06 21:49:32 +08:00   ❤️ 2
    这不叫递归啊~
    murmur
        4
    murmur  
       2017-04-06 21:51:30 +08:00
    对了,如果你会用英文搜索的话,你会发现有一种优雅的写法可以像 Promise.all 一样让一个数组的 promise 按顺序执行,而且不用自己串链子

    问题是好像这个方法用的是 reduce 方法,一样需要 polyfill
    binux
        5
    binux  
       2017-04-06 21:52:17 +08:00
    Promise
    coderfox
        6
    coderfox  
       2017-04-06 21:59:09 +08:00 via Android
    let req = axois.request(...).then(业务逻辑).then( () => req );
    req();

    思路大概如此,或许有点小问题,自己试试。
    billlee
        7
    billlee  
       2017-04-06 21:59:41 +08:00
    alexsunxl
        8
    alexsunxl  
       2017-04-06 22:34:26 +08:00
    上 babel , async await
    viko16
        9
    viko16  
       2017-04-06 22:43:06 +08:00 via Android
    websocket 会不会是更好的方案?
    golmic
        10
    golmic  
       2017-04-06 22:54:20 +08:00 via Android
    对啊,我也觉得上 socket
    Biwood
        11
    Biwood  
       2017-04-06 22:58:55 +08:00
    写聊天程序?长轮询?这个很常见吧,异步回调而已,不算递归,没有那么高大上
    vghdjgh
        12
    vghdjgh  
       2017-04-06 23:13:25 +08:00
    1 、就用递归的写法(纯函数式语言的标准写法啊,不丑的)
    即:每次只处理第一个 promise ,处理后把数组的其它部分作为新数组递归执行,直到全部完成
    2 、 async/await
    类似于:
    ```
    async function main(promises) { // promises 是一个 promise 数组
    let result = 0;
    for(let promise of promises) {
    result += await promise;
    }
    return result;
    }
    ```
    3 、和后端商量下用 websocket 推数据给你(现在轮询的方式很落后了吧)。
    abcbuzhiming
        13
    abcbuzhiming  
    OP
       2017-04-06 23:18:56 +08:00
    @viko16 条件不允许上 websocket
    abcbuzhiming
        14
    abcbuzhiming  
    OP
       2017-04-06 23:19:42 +08:00
    @vghdjgh
    @coderfox
    谢谢,正在研究改造成 promise ,环境暂时不允许用 async
    shyling
        15
    shyling  
       2017-04-06 23:22:03 +08:00
    Rx.Observable.from(...)
    .flatMap(source => fetch(source), 1)
    .subscrible()
    lujiajing1126
        16
    lujiajing1126  
       2017-04-06 23:37:27 +08:00
    支持#15

    把 Promise 转成 Observable ,然后用 rxjs/repeatproto 来重复执行

    https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/repeatproto.md
    otakustay
        17
    otakustay  
       2017-04-06 23:43:14 +08:00
    转 rx 是个办法但侵入性太强,其实你用 promise 或 callback 的话直接找个 async 库做下 series 封装就行了
    http://caolan.github.io/async/
    lkytal
        18
    lkytal  
       2017-04-06 23:47:00 +08:00
    async 库就解决了...
    zbinlin
        19
    zbinlin  
       2017-04-06 23:56:02 +08:00 via Android
    自荐一个类似的 async 库: https://www.npmjs.com/package/serial-async

    :)
    libook
        20
    libook  
       2017-04-07 00:33:43 +08:00
    这是一个流程控制库 https://caolan.github.io/async/index.html
    zhouyg
        21
    zhouyg  
       2017-04-07 00:55:24 +08:00   ❤️ 1
    不用库就可以有优雅的写法:
    [promiseFn1, promiseFn2,promiseFn3].reduce((promise, fn)=>{
    return promise.then(fn);
    },promiseFn0() );
    coldsnap
        22
    coldsnap  
       2017-04-07 01:40:59 +08:00
    ```
    function each (promises, cb) {
    return promises.reduce((promise, task, i) => {
    return promise.then(_ => task).then(_ => cb(_, i))
    }, Promise.resolve())
    }
    ```

    用法和 bluebird 的 each 一样。
    ref: http://bluebirdjs.com/docs/api/promise.each.html
    dangyuluo
        23
    dangyuluo  
       2017-04-07 06:36:50 +08:00
    感觉 websocket 才是正解。
    ryanzyy
        24
    ryanzyy  
       2017-04-07 16:49:10 +08:00
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2673 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 02:02 · PVG 10:02 · LAX 19:02 · JFK 22:02
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.