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

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


今有一题,题目为:

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

伪代码为:

  1. Ajax1({
  2. ...
  3. success: function(data){
  4. CODE1 = data
  5. }
  6. })
  7. Ajax2({
  8. ...
  9. success: function(data){
  10. CODE2 = data
  11. }
  12. })
  13. myFunc(CODE1, CODE2)

立Flag判断

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

使用了setTimeOut来模拟ajax:

  1. let CODE1 = null
  2. let CODE2 = null
  3. function myFunc() {
  4. console.log(CODE1, CODE2);
  5. }
  6. //第一种
  7. let flag = 0 //flag默认为0
  8. function ajax1() {
  9. setTimeout(() => {
  10. console.log('ajax1得到响应')
  11. CODE1 = 'ajax1返回的数据'
  12. //如果回调时flag为1,代表另一个ajax已经初始化成功
  13. if (flag === 1) {
  14. myFunc()
  15. } else {
  16. //否则flag+1代表本ajax成功
  17. flag += 1
  18. }
  19. }, 1000)
  20. }
  21. function ajax2() {
  22. setTimeout(() => {
  23. console.log('ajax2得到响应')
  24. CODE2 = 'ajax2返回的数据'
  25. if (flag === 1) {
  26. myFunc()
  27. } else {
  28. flag += 1
  29. }
  30. }, 2000)
  31. }
  32. ajax1()
  33. ajax2()

执行结果:

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

yield关键字

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

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

  1. //第二种
  2. //Promise执行器
  3. function run(gen) {
  4. gen = gen()
  5. return next(gen.next())
  6. function next({ done, value }) {
  7. return new Promise(resolve => {
  8. if (done) {
  9. resolve(value)
  10. } else {
  11. value.then(data => {
  12. next(gen.next(data)).then(resolve)
  13. })
  14. }
  15. })
  16. }
  17. }
  18. function ajax1() {
  19. return new Promise(resolve => {
  20. setTimeout(() => {
  21. console.log('ajax1得到响应');
  22. CODE1 = 'ajax1返回的数据'
  23. resolve()
  24. }, 5000)
  25. })
  26. }
  27. function ajax2() {
  28. return new Promise(resolve => {
  29. setTimeout(() => {
  30. console.log('ajax2得到响应');
  31. CODE2 = 'ajax2返回的数据'
  32. resolve()
  33. }, 5000)
  34. })
  35. }
  36. function* call() {
  37. let aj1 = ajax1()
  38. let aj2 = ajax2()
  39. yield aj1
  40. yield aj2
  41. }
  42. run(call).then(myFunc)

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

async/await关键字

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

  1. // 第三种
  2. function ajax1() {
  3. return new Promise(resolve => {
  4. setTimeout(() => {
  5. console.log('ajax1得到响应');
  6. CODE1 = 'ajax1返回的数据'
  7. resolve()
  8. }, 1000)
  9. })
  10. }
  11. function ajax2() {
  12. return new Promise(resolve => {
  13. setTimeout(() => {
  14. console.log('ajax2得到响应');
  15. CODE2 = 'ajax2返回的数据'
  16. resolve()
  17. }, 2000)
  18. })
  19. }
  20. async function call() {
  21. /*
  22. 这里不能这么写:
  23. await ajax1()
  24. await ajax2()
  25. 这样会在ajax1之后才会执行ajax2
  26. 需要写成下面的这种:
  27. */
  28. let aj1 = ajax1()
  29. let aj2 = ajax2()
  30. await aj1
  31. await aj2
  32. myFunc()
  33. }
  34. call()

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

Promise

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

  1. //第四中,同时也是最优解
  2. function ajax1(resolve, reject) {
  3. setTimeout(()=>{
  4. console.log('ajax1得到响应');
  5. CODE1 = 'ajax1返回的数据'
  6. resolve()
  7. },1000)
  8. }
  9. function ajax2(resolve, reject) {
  10. setTimeout(()=>{
  11. console.log('ajax2得到响应');
  12. CODE2 = 'ajax2返回的数据'
  13. resolve()
  14. },2000)
  15. }
  16. const p1 = new Promise(ajax1)
  17. const p2 = new Promise(ajax2)
  18. Promise.all([p1, p2]).then(myFunc)

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

用四种方法将两个AJAX改为同步的更多相关文章

  1. 两个变量交换的四种方法(Java)

    对于两种变量的交换,我发现四种方法,下面我用Java来演示一下. 1.利用第三个变量交换数值,简单的方法. (代码演示一下) class TestEV //创建一个类 { public static ...

  2. Java中取小数点后两位(四种方法)

    摘自http://irobot.iteye.com/blog/285537 Java中取小数点后两位(四种方法)   一 Long是长整型,怎么有小数,是double吧     java.text.D ...

  3. Android提交数据到服务器的两种方式四种方法

    本帖最后由 yanghe123 于 2012-6-7 09:58 编辑 Android应用开发中,会经常要提交数据到服务器和从服务器得到数据,本文主要是给出了利用http协议采用HttpClient方 ...

  4. 两个变量交换的四种方法(Java) 七种方法(JS)

    两个变量交换的四种方法(Java)   对于两种变量的交换,我发现四种方法,下面我用Java来演示一下. 1.利用第三个变量交换数值,简单的方法. (代码演示一下) 1 class TestEV 2 ...

  5. 关于fmri数据分析的两大类,四种方法

    关于fmri数据分析的两大类,四种方法: 数据驱动: tca:其实这种方法,主要是提取时间维的特征.如果用它来进行数据的分析,则必须要利用其他的数据方法,比如结合ICA. ica:作为pca的一般化实 ...

  6. 织梦DedeCMS模板防盗的四种方法

    织梦(DedeCMS)模板也是一种财富,不想自己辛辛苦苦做的模板被盗用,在互联网上出现一些和自己一模一样的网站,就需要做好模板防盗.本文是No牛收集整理自网络,不过网上的版本都没有提供 Nginx 3 ...

  7. Angular--页面间切换及传值的四种方法

    1. 基于ui-router的页面跳转传参(1) 在AngularJS的app.js中用ui-router定义路由,比如现在有两个页面,一个页面(producers.html)放置了多个produce ...

  8. C#播放声音的四种方法 +AxWindowsMediaPlayer的详细用法

    C#播放声音的四种方法 第一种是利用DirectX 1.安装了DirectX SDK(有9个DLL文件).这里我们只用到MicroSoft.DirectX.dll和 Microsoft.Directx ...

  9. IOS中Json解析的四种方法

    作为一种轻量级的数据交换格式,json正在逐步取代xml,成为网络数据的通用格式. 有的json代码格式比较混乱,可以使用此“http://www.bejson.com/”网站来进行JSON格式化校验 ...

随机推荐

  1. Python中的进制表示方式及转换方法

    在Python中,非十进制数字的表示方式为: 二进制:前面加0b,如0b1001 八进制:前面加0o,如0o3562 十六进制:前面加0x,如0x2af3 不同进制数字可直接进行数学计算,结果返回十进 ...

  2. jdk动态代理和cglib动态代理底层实现原理超详细解析(jdk动态代理篇)

    代理模式是一种很常见的模式,本文主要分析jdk动态代理的过程 1.举例 public class ProxyFactory implements InvocationHandler { private ...

  3. Codeforces1303C. Perfect Keyboard

    本题可以转换成图论来做,每两个相邻点连一条边,然后统计每一个点的degree,如果>=2说明有一个点要相邻三个点,不满足题意,然后找出每个degree<2的点,这些点可以作为一段的起点,然 ...

  4. Solr与tomcat搭建(搭建好)

    https://pan.baidu.com/s/1kXagNYJ  密码:hgxd

  5. c++类的创建与使用

    c++类的创建与使用 前言: 之前一直对c++的类的创建与使用不太熟悉,有些概念还是有点模糊,借着这次休息的机会整理一下对应是知识点.如有不正确的地方还希望各位读者批评指正. 一.C++中public ...

  6. 四 动态sql 标签的使用(if&where&sql片段&foreach)

    if标签的使用: userMapper.xml  userMapper.java junit: where标签: 注意:写了where标签就不用手动写where语句 sql片段的设置和调用: forr ...

  7. 《React后台管理系统实战 零》:基础笔记

    day01 1. 项目开发准备 1). 描述项目 2). 技术选型 3). API接口/接口文档/测试接口 2. 启动项目开发 1). 使用react脚手架创建项目 2). 开发环境运行: npm s ...

  8. 一套完整的javascript面试题(转)

    一.单选题1.以下哪条语句会产生运行错误:(a)A.var obj = ();//语法错误B.var obj = [];//创建数组C.var obj = {};//创建对象D.var obj = / ...

  9. 「POI2015」KIN

    传送门 Luogu 解题思路 想要做这道题,只要会维护区间最大子段和就好了. 而这个可以用线段树维护模板点这里 对于重复的情况,我们可以对每一个位置记一个前驱表示和当前位置种类相同的前一个位置. 然后 ...

  10. 吴裕雄--天生自然JAVA数据库编程:PrepareStatement

    import java.sql.Connection ; import java.sql.DriverManager ; import java.sql.SQLException ; import j ...