前端JS在循环语句中调用API并保证循环语句外同函数作用域的代码同步执行

news/2024/11/23 23:26:12/

一、前言

在开发中,可能难免会遇到需要将某个数组遍历获取指定字段的值,然后用此值作为参数来调用API的场景。那么,JS如何在循环语句中调用API并且保证同函数作用域中的其他代码同步执行,并且能使用循环语句中多次调用API请求到的全部数据?我们一起来看看:

二、问题描述、分析和解决

2.1、问题描述

这几天,在进行一个使用到百度地图多点标注的功能开发,标注点的数量,经纬度坐标值,以及其他数据,均需动态用API获取。此API有一个参数,需从一个对象数组([{},{},{},…])中获取,这个数组中的每个对象元素中有此API的参数,所以需要用到循环遍历并调用API。如何在一个函数作用域中,先执行完这个含有多次接口调用的循环,再执行此循环语句后面的代码成了一个不大不小的问题。

2.2、问题分析(求道)

对于这种情况,我想要的执行逻辑是:每循环一次,得到一个value,然后用这个value作为参数调用一次API得到一条目标数据。最后,将在循环语句中多次调用API得到的数据,存储到sessionstorage中供在地图中打点标注。因为只有让此函数作用域中的代码都同步执行,才能保证最终数据的完整和正常。
所以,此问题解决思路的方向,就是要让所有的异步变同步,此函数作用域内,所有的代码同步执行。

2.3、问题解决(求术)

有术无道止于术,有道无术术可求。
有上面求道部分的支持,接下来解决这个问题就变得明了和直接了:

  • 我计划用async await来使异步“变”同步;
  • 找一个可以使用async await的循环语句(这个不是废话,诸君接着看);
    好了,执行步骤就是这两步,接下来直接上代码:
...// 因为我是基于React开发,所以函数定义形式只供参考。async关键字登场const recycleGetData = async (data) => {const projAddInfo = [];// 用async await保证有异步调接口的循环体变同步,对循环语句种类有一定限制,我这里使用的是for循环,用for of循环替代fro循环也可以达到预期效果,别的循环诸君也可以试试,map是不可以的,我试过了。for (let i = 0; i < data.length; i++) {// await在此处登场,这不仅可以保证for循环内代码同步执行,还可以使整个函数作用域内的“代码块”同步执行。const apiResult = await yourAPIName(data[i].value);if (apiResult == null) {continue;}const obj = {};if (apiResult.Key === 'XXX') {const locationArr = apiResult.Value.split(',');obj['lng'] = locationArr[0];obj['lat'] = locationArr[1];obj['proAddress'] = locationArr[2];obj['projName'] = data[i].title ? data[i].title : data[i].label;...}projAddInfo.push(obj); }// 用async await控制过的for循环,便可保证先执行完for循环,拿到循环内每次调用接口调用的返回值,再执行下面的代码console.log(projAddInfo)};
...const function1 = async () => {...await yourAPIName1()...const data = [{XXX},{XXX},{XXXX},...];await recycleGetData(data);...}
...

从上面代码和其中的注释可以就可以理解,问题解决的第二步思路“ 找一个可以使用async await的循环语句”为什么我说它不是一句废话,因为有的循环语句是达不到我们的预期目的的(除了我试过的map语句,有的博主也提到了foreach语句也无法达到预期,诸君有谁感兴趣,可以一试)。
下面再来看看与本片内容主体相关的一些前端技术知识点,以作为本篇博文的扩充内容。

三、JS作用域、promise、async await知识扩展

3.1、JS作用域

JS的作用可以说是可访问变量的集合,其可根据范围分为局部作用域和全局作用域,函数作用域是局部作用域。为了和本篇博文主要内容贴合,关于局部作用域,在本博文中,用函数作用域来管中窥豹。

  1. 全局作用域
    • 直接写在script标签的JS代码,都在全局作用域;
    • 全局作用域在页面打卡的时候创建,在页面关闭时销毁;
    • 全局作用域中的变量都是全局变量,在页面的任意的部分都可以访问到。
  2. 函数作用域(是局部作用域)
    • 每调用一次函数就会创建一个新的函数作用域,它们之间是相互独立的;
    • 调用函数时创建函数作用域,函数执行完毕以后,作用域销毁;
    • 在函数作用域中可以访问全局变量,但在全局作用域中无法访问到局部变量。

3.2、promise

我们肯定都听过“回调地狱”这个术语,它其实就是JS 处理异步时使用回调函数,一个回调函数执行完成,进行下一个回调函数。这样会导致层层嵌套,代码不清晰。这是在promise出现之前,JS对异步的处理方式。promise的出现,直接让我们可以避开代码不清晰的“回调地狱”。一起来了解一下promise的一些基本知识吧:

  1. promise的状态
    promise 有三种状态 :pending(进行中),resolved(成功),rejected(失败),并且它的状态是不可逆的。不可逆就是pending—>resolved或pending—>rejected。
  2. promise 有两个回调函数
    promise 的参数是一个函数,函数里还有两个参数:resolved,rejected。
    • resolved(res) 处理成功的 函数 它传递的参数 会在then方法里输出;
    • rejected(err) 处理失败的函数 它传递的参数 会在 catch方法里输出。
  3. 多个promise的执行
    • promise.all(多个promise同时执行):它的参数是多个promise函数,直到最慢的一个promise执行完毕才返回所有的promise的结果,有一个promise函数崩溃,整个promise就崩溃,故要慎用;
    • promise.race:多个promise 执行速度pk看谁的速度最快,返回最快的promise的结果。

3.3、async await

  1. async
    带async关键字的函数,是声明异步函数,返回值是promise对象,如果async关键字函数返回的不是promise,会自动用Promise.resolve()包装。
  2. await
    带await关键字的语句,等待右侧表达式的结果,这个结果是promise对象或者其他值。
    如果它等到的不是一个 promise 对象,那 await 表达式的运算结果就是它等到的东西。
    如果它等到的是一个 promise 对象,await 就忙起来了,它会阻塞后面的代码,等着 promise 对象 resolve,然后得到 resolve 的值,作为 await 表达式的运算结果。

四、说明

参考链接
JavaScript函数作用域
js中数组for循环调用后端接口,返回数据填充入数组
JS中async与await详解
js promise 详解
欢迎大家一起讨论、学习


http://www.ppmy.cn/news/165468.html

相关文章

(2022,DynamicD)使用动态鉴别器改进 GAN

Improving GANs with A Dynamic Discriminator 公众号&#xff1a;EDPJ 目录 0. 摘要 1. 简介 2. 相关工作 3. 方法 3.1 基础 3.2 动态鉴别器 3.3 针对不同数据体系的两种方案 4. 实验 4.1 设置 4.2 实证研究 4.3 与现有方法的比较 4.4 DynamicD 的泛化性和兼…

「科普向」SaaS 是什么?

简介 在当今数字化时代&#xff0c;软件即服务&#xff08;Software as a Service&#xff0c;简称SaaS&#xff09;成为企业和个人在云计算领域中的一种常见选择。SaaS是一种软件交付模式&#xff0c;用户通过互联网访问和使用云端的软件应用&#xff0c;而不必购买、安装和维…

趣谈代码中的注释

代码注释应该算是最具争议的话题之一了。每当程序员们讨论这个话题&#xff0c;可谓是公有公理&#xff0c;婆有婆理。 该不该写注释 四位不同风格的程序员进行了一场辩论&#xff0c;他们分别是唐僧、悟空、八戒、沙僧。 唐僧&#xff1a;自项目成立三年以来&#xff0c;我…

5236. 美化数组的最少删除数

给你一个下标从 0 开始的整数数组 nums &#xff0c;如果满足下述条件&#xff0c;则认为数组 nums 是一个 美丽数组 &#xff1a; nums.length 为偶数 对所有满足 i % 2 0 的下标 i &#xff0c;nums[i] ! nums[i 1] 均成立 注意&#xff0c;空数组同样认为是美丽数组。 你…

致态TiPro7000固件Firmware更新+升级软件(英韧IG5236主控)

致态对TiPro7000的固件&#xff08;Firmware&#xff09;进行了多次优化。版本从3.2.F.3C更到ZTA32F3Y&#xff0c;又更新到ZT32F46&#xff0c;再更新到ZT32F66。 1、安装SSD至个人电脑&#xff08;Windows系统盘或数据盘&#xff09;。 2、下载RMATool_V11.rar&#xff0c;…

1N5236BTR稳压二极管

产品型号&#xff1a;1N5236BTR   商品目录&#xff1a;稳压二极管   精度&#xff1a;5%   稳压值(典型值&#xff09;&#xff1a;7.5V   反向漏电流&#xff1a;3uA6V   最大功率&#xff1a;500mW 产品展示&#xff1a; 绝对最大额定参数&#xff1a;   超过绝…

HDU5236(概率DP,贪心)

题意是敲n个字符&#xff0c;每次敲有p概率崩溃返回上一次的保存状态&#xff0c;保存需要按下x个建。求最小的按键次数的期望。 求出敲n个字母的期望后枚举分成i段&#xff0c;要使得尽量均匀。 #include <bits/stdc.h> using namespace std; #define maxn 111111 #def…

Hdu 5236 Article(dp)

题目链接 Article Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 404 Accepted Submission(s): 119 Problem Description As the term is going to end, DRD begins to write his final article. DRD uses …