美文网首页
vue利用Promise实现axios发送ajax异步函数顺序执

vue利用Promise实现axios发送ajax异步函数顺序执

作者: John_Phil | 来源:发表于2021-02-15 20:32 被阅读0次

问题引入

首先提出一个问题:点击页面上一个按钮发送两个ajax请求,其中一个请求会不会等待另一个请求执行完毕之后再执行?
  答案是:不会,这两个异步请求会同时发送,至于执行的快与慢,要看响应的数据量的大小及后台逻辑的复杂程度。
  从异步请求的执行原理来看,我们知道当一个异步请求发送时,浏览器不会处于锁死、等待的状态,从一个异步请求发送到获取响应结果的期间,浏览器还可以进行其它的操作。这就意味着多个异步请求的执行时并行的。

场景

  • 有a、b、c三个异步任务,要求必须先执行a,再执行b,最后执行c
  • 且下一次任务必须要拿到上一次任务执行的结果,才能做操作

思路

  • 我们需要实现一个队列,将这些异步函数添加进队列并且管理它们的执行,队列具有First In First Out的特性,也就是先添加进去的会被先执行,接着才会执行下一个(注意跟栈作区别)
  • 大家也可以类比一下jQuery的animate方法,添加多个动画也会按顺序执行

解决办法

// 异步函数a
var a = function () {
  return new Promise(function (resolve, reject) {
    setTimeout(function () {
      resolve('a')
    }, 1000)
  })
}

// 异步函数b
var b = function (data) {
  return new Promise(function (resolve, reject) {
    resolve(data + 'b')
  })
}

// 异步函数c
var c = function (data) {
  return new Promise(function (resolve, reject) {
    setTimeout(function () {
      resolve(data + 'c')
    }, 500)
  })
}

解决方法一(使用then链式操作)

特点:可以满足需求,但是书写比较繁琐

//链式调用
a()
  .then(function (data) {
    return b(data)
  })
  .then(function (data) {
    return c(data)
  })
  .then(function (data) {
    console.log(data)// abc
  })

方法二(构建队列)

特点:封装方法,可移植到别处使用


// 构建队列
function queue(arr) {
  var sequence = Promise.resolve()
  arr.forEach(function (item) {
    sequence = sequence.then(item)
  })
  return sequence
}

// 执行队列
queue([a, b, c])
  .then(data => {
    console.log(data)// abc
  })

方法三(使用async、await构建队列)

特点:同方法二

async function queue(arr) {
  let res = null
  for (let promise of arr) {
    res = await promise(res)
  }
  return await res
}
queue([a, b, c])
  .then(data => {
    console.log(data)// abc
  })

Promise.reduce也可以用来顺序执行函数,但是可使用的场景非常有限,一般用来读取文件信息,而以上给出的方法,不管你在异步函数中做了什么,只要函数最后返回了一个Promise对象,都可以使用。

promise结合axios在vue中的实例

前台代码

<template>
    <div>
   
            <el-button   @click="method1()" >method1</el-button>

            <el-button   @click="method2()" >method2</el-button>
         
            <el-button   @click="method3()" >method3</el-button>

            <el-button   @click="method4()" >method4</el-button>

            <el-button   @click="method5()" >method5</el-button>
    </div>
</template>

<script>
export default {
    name:"PromiseTest",
    methods:{
        method1(){

            this.axios.post("/getspringbootproxy/ajax1").then(res => {
                console.log("ajax1")
                console.log(res)
                
            
              });
            this.axios.post("/getspringbootproxy/ajax2").then(res => {
                console.log("ajax2")
                console.log(res)
                
            
              });

        },
        method2(){

            this.axios.post("/getspringbootproxy/ajax1").then(res => {
                console.log("ajax1")
                console.log(res)
                 this.axios.post("/getspringbootproxy/ajax2").then(res => {
                console.log("ajax2")
                console.log(res)
              });
            
              });
           

        },
        method3(){
            
             this.axios.all([this.method3axios1(), this.method3axios2(),this.method3axios3()])
            .then(this.axios.spread(function (res1, res2,res3) {
                // 两个请求现在都执行完成
                 console.log("method3axios1 method3axios2")
                 console.log(res1)
                 console.log(res2)
                 console.log(res3)
            }));
        },
        method3axios1(){
            
            //  this.axios.post("/getspringbootproxy/ajax1").then(res => {
            //     console.log("ajax1")
            //     console.log(res)
            //   });
            return this.axios.post("/getspringbootproxy/ajax1");
        },
        method3axios2(){
            
            //  this.axios.post("/getspringbootproxy/ajax2").then(res => {
            //     console.log("ajax2")
            //     console.log(res)
            //   });
              return this.axios.post("/getspringbootproxy/ajax2");
        },
        method3axios3(){
            
            //  this.axios.post("/getspringbootproxy/ajax2").then(res => {
            //     console.log("ajax2")
            //     console.log(res)
            //   });
              return this.axios.post("/getspringbootproxy/ajax3");
        },
         method4(){
            
                // const p1 = new Promise(function (resolve, reject) {
                // setTimeout(() => reject(new Error('fail')), 3000)
                // })

                // const p2 = new Promise(function (resolve, reject) {
                // setTimeout(() => resolve(p1), 1000)
                // })

                // p2
                // .then(result => console.log(result))
                // .catch(error => console.log(error))
                // Error: fail
                new Promise((resolve, reject) => {
                 return resolve(this.axios.post("/getspringbootproxy/ajax1"));
               
                }).then(r => {
                     console.log(r)
                     new Promise((resolve, reject) => {
                     return resolve(this.axios.post("/getspringbootproxy/ajax2"));
                    
                    }).then(r => {
                         console.log(r)
                         new Promise((resolve, reject) => {
                            return resolve(this.axios.post("/getspringbootproxy/ajax3"));
                            
                            }).then(r => {
                                console.log(r)
                            });
                    });
                });
         },
         method5(){
            //  因为resolve跟reject这两个参数是可以省略的,所以可以把new Promise(...)写成Promise.resolve或者Promise.reject的形式.
            new Promise((resolve, reject) => {
                        return resolve(this.axios.post("/getspringbootproxy/ajax1"));
                }).then(r => {
                        console.log(r)
                        return Promise.resolve(this.axios.post("/getspringbootproxy/ajax2"));
                    })
                    .then(r => {
                        console.log(r)
                        return Promise.resolve(this.axios.post("/getspringbootproxy/ajax3"));
                            
                    })
                    .then(r => {
                                console.log(r)
                            });
                    
            
         }
        
        
     }

}
</script>

<style>

</style>

后台代码

  @PostMapping("/ajax1")
    public Message method7(){
        System.out.println("ajax1 5000");
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        Message msg=    new Message<User>();
        msg.setCode(1001);
        msg.setMsg("ajax1 5000");
        return msg;
    }
    @PostMapping("/ajax2")
    public Message method8(){
        System.out.println("ajax2 2000");
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        Message msg=    new Message<User>();
        msg.setCode(1002);
        msg.setMsg("ajax2 2000");
        return msg;
    }
    @PostMapping("/ajax3")
    public Message method9(){
        System.out.println("ajax3 1000");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        Message msg=    new Message<User>();
        msg.setCode(1003);
        msg.setMsg("ajax3 1000");
        return msg;
    }

结果会发现 前台按钮中

method1 异步请求 按照后台响应时间来调用回调函数
method2 ,method4,method5 按同步顺序执行 ajax1 ajax2 ajax3
method3 异步请求 但是都执行结束后才会执行后续方法

结论

如果想通过同步来控制ajax执行顺序,前一次的执行结果放入到下一个ajax请求中,可以使用method2,4,5。
如果可以通过异步执行ajax但是执行结果不用放到其他ajax请求中,只是再都请求结束后要对执行结果有顺序要求可以使用method3速度比method5 同步执行速度快。
如果无任何顺序要求,仅需要返回结果进行渲染可以用method1。

相关文章

  • vue利用Promise实现axios发送ajax异步函数顺序执

    问题引入 首先提出一个问题:点击页面上一个按钮发送两个ajax请求,其中一个请求会不会等待另一个请求执行完毕之后再...

  • 发送ajax请求

    发送ajax请求 vue本身不支持发送ajax请求,需要使用vue-resourc axios等插件实现,建议使用...

  • 14.axios使用

    现在vue发送ajax请求官方推荐使用axios,现在以13.Vue-Resource 使用案例用axios实现效...

  • Vue(3)

    一、Vue中的ajax:vue-resource和axios vue-resource是Vue实现异步加载的官方库...

  • 使用 axios 发送 ajax 请求

    1)vue本身不支持发送AJAX请求,需要使用vue-resource、axios等插件实现。2) axios是一...

  • Promise和async\await

    回调函数 用来处理异步问题,例如发送Ajax,setTimeout等 Promise 封装的例子 async\await

  • JavaScript 控制异步走向的几种方式

    使用 setTimeout 实现异步,通过函数执行顺序、回调函数、promise 对象、async 和 await...

  • 面试题

    axios和ajax的区别 axios是通过promise实现对ajax技术的一种封装axios可以运行nodej...

  • 04Vue的前后端交互

    Vue的前后端交互 Promise用法 异步调用 触发异步调用的方式定时任务Ajax事件函数 多次异步调用的依赖分...

  • axios的基本使用

    axios的安装和引入 Axios 是一个基于 promise 的 HTTP 库,在vue中使用axios进行异步...

网友评论

      本文标题:vue利用Promise实现axios发送ajax异步函数顺序执

      本文链接:https://www.haomeiwen.com/subject/yjgyxltx.html