• 用四种方法将两个AJAX改为同步


    用四种方法将两个AJAX改为同步

    Promise、Generator函数、yield、async/await 相关


    今有一题,题目为:

    1. 现有ajax1()ajax2(),用于快速初始化CODE1和CODE2
    2. myFunc必须在CODE1和CODE2初始化之后再执行
    3. 可以在原代码上修改

    伪代码为:

    Ajax1({
        ...
        success: function(data){
            CODE1 = data
        }
    })
    
    Ajax2({
        ...
        success: function(data){
            CODE2 = data
        }
    })
    
    myFunc(CODE1, CODE2)
    

    立Flag判断

    作为一个后端,我最先想到的是创建一个变量来标志两个ajax是否完成,然后再两个ajax的回调中进行判断(至于两个ajax都改为同步这种方法直接不考虑),大致代码如下:

    使用了setTimeOut来模拟ajax:

    let CODE1 = null
    let CODE2 = null
    function myFunc() {
      console.log(CODE1, CODE2);
    }
    
    //第一种
    let flag = 0 //flag默认为0
    
    function ajax1() {
      setTimeout(() => {
        console.log('ajax1得到响应')
        CODE1 = 'ajax1返回的数据'
        //如果回调时flag为1,代表另一个ajax已经初始化成功
        if (flag === 1) {
          myFunc()
        } else {
          //否则flag+1代表本ajax成功
          flag += 1
        }
      }, 1000)
    }
    
    function ajax2() {
      setTimeout(() => {
        console.log('ajax2得到响应')
        CODE2 = 'ajax2返回的数据'
    
        if (flag === 1) {
          myFunc()
        } else {
          flag += 1
        }
      }, 2000)
    }
    
    ajax1()
    ajax2()
    

    执行结果:

    第一种

    可以看到myFunc在两个ajax执行完成之后才执行。

    yield关键字

    yield关键字是ES6添加的语法,可以在函数执行中交出运行权限

    上面第一种方法一看就是不会前端的人写的,前端如果要想炫技的话可以这么写:

    //第二种
    
    //Promise执行器
    function run(gen) {
      gen = gen()
      return next(gen.next())
    
      function next({ done, value }) {
        return new Promise(resolve => {
          if (done) {
            resolve(value)
          } else {
            value.then(data => {
              next(gen.next(data)).then(resolve)
            })
          }
        })
      }
    }
    
    function ajax1() {
      return new Promise(resolve => {
        setTimeout(() => {
          console.log('ajax1得到响应');
          CODE1 = 'ajax1返回的数据'
          resolve()
        }, 5000)
      })
    }
    
    function ajax2() {
      return new Promise(resolve => {
        setTimeout(() => {
          console.log('ajax2得到响应');
          CODE2 = 'ajax2返回的数据'
          resolve()
        }, 5000)
      })
    }
    
    function* call() {
      let aj1 = ajax1()
      let aj2 = ajax2()
      yield aj1
      yield aj2
    }
    
    run(call).then(myFunc)
    

    什么意思我解释不清楚,也不想解释,自己去看阮一峰的博客:Generator 函数的含义与用法

    async/await关键字

    async/await关键字是ES7的语法,是对上面Promise执行器的一种简化:

    // 第三种
    
    function ajax1() {
      return new Promise(resolve => {
        setTimeout(() => {
          console.log('ajax1得到响应');
          CODE1 = 'ajax1返回的数据'
          resolve()
        }, 1000)
      })
    }
    
    function ajax2() {
      return new Promise(resolve => {
        setTimeout(() => {
          console.log('ajax2得到响应');
          CODE2 = 'ajax2返回的数据'
          resolve()
        }, 2000)
      })
    }
    
    async function call() {
    	/* 
        这里不能这么写:
        await ajax1()
        await ajax2()
        这样会在ajax1之后才会执行ajax2
        需要写成下面的这种:
    	*/
      let aj1 = ajax1()
      let aj2 = ajax2()
      await aj1
      await aj2
      myFunc()
    }
    
    call()
    

    async声明这是一个内部存在同步的函数,只有声明了async,函数内部才能使用await,await代表等待Promise执行完毕才会继续执行,的确有点同步的感觉了。

    Promise

    上面用到了Promise但是都没介绍,就是想把最合适的一种放到最后:

    //第四中,同时也是最优解
    
    function ajax1(resolve, reject) {
        setTimeout(()=>{
            console.log('ajax1得到响应');   
            CODE1 = 'ajax1返回的数据'
            resolve()
        },1000)
    }
    
    function ajax2(resolve, reject) {
        setTimeout(()=>{
            console.log('ajax2得到响应');   
            CODE2 = 'ajax2返回的数据'
            resolve()
        },2000)
    }
    
    const p1 = new Promise(ajax1)
    const p2 = new Promise(ajax2)
    
    Promise.all([p1, p2]).then(myFunc)
    

    函数Promise.all()接收一个Promise数组参数,作用是数组内的Promise执行完毕之后会返回一个Promise对象。(还有一个Promise.race()方法也挺好玩,作用是参数中任意一个Promise完成就返回一个Promise)

  • 相关阅读:
    进程,进程
    hmac和socketserver
    下载Eclipse、下载Java各个版本,来这里就对了
    Java循环语句怎么用?经典排序算法见真知
    CSS基本语法
    Html属性标签
    HTML标记大全参考手册
    composer 安装Laravel (win10)
    composer 安装(win)
    GIT
  • 原文地址:https://www.cnblogs.com/lixin-link/p/11704184.html
Copyright © 2020-2023  润新知