当前位置: 首页 > news >正文

【前端学习】前端高频面试场景题

前端高频面试场景题

面试官问:如果有100个请求,你如何使用Promise控制并发?

如何使用Promise控制并发请求?

并发控制是指在处理多个任务时,限制同一时刻正在执行的任务数量,而不是一次性发起所有任务。

它关乎的是 “同时进行” 的数量,而不是 “总共要完成” 的数量。

在JavaScript中,由于它是单线程的,所谓的“并发”执行异步任务(如网络请求),实际上是指:

  1. 同时发起了N个请求,并且不等待其中一个完成就立即发起下一个,直到达到并发上限。
  2. 然后,通过事件循环和回调机制,同时处理这N个请求的响应

所以,并发控制的核心流程可以概括为:

1. 初始化:启动 K 个任务(达到并发上限)。
2. 监听:任何一个任务完成,就立刻从等待队列中取出下一个任务开始执行。
3. 循环:重复步骤2,直到所有任务都完成。
4. 结束:返回所有任务的结果。

核心思路是:创建一个“并发池”,当池子有空位时,就放入新的任务;任务完成后,从池中移除,并放入下一个等待的任务。

可以通过一个 Pool 类或者一个函数来实现这个逻辑

  1. Promise

  •  * 控制异步任务的并发执行数量
     * @param {Array} tasks 异步任务数组,每个任务是一个返回Promise的函数
     * @param {number} limit 最大并发数
     * @returns {Promise<any[]>} 所有任务完成后的结果数组
     */
    function promisePool(tasks, limit) {
    // 用于存储所有任务的结果,按顺序返回
    const results = [];
    // 创建一个可迭代的迭代器,用于按顺序获取任务
    const iterator = tasks.entries();
    // 存储当前正在执行的Promise(用于Promise.all)
    const executing = new Set();

    // 递归函数:从迭代器中获取下一个任务并执行
    const enqueue = () => {
    const { value, done } = iterator.next();

    // 如果所有任务都已分配,且当前没有正在执行的任务,则彻底结束
    if (done && executing.size === 0) {
    return Promise.resolve();
    }

    // 如果还有任务且当前并发数未达到上限
    if (!done && executing.size < limit) {
    const [index, task] = value;

    // 执行当前任务
    const promise = task().then(result => {
    results[index] = result; // 将结果存储到对应的位置
    executing.delete(promise); // 任务完成,从执行集中移除
    });

    executing.add(promise); // 将新任务的Promise加入执行集

    // 无论当前任务成功还是失败,都继续调度下一个任务
    return promise.catch(() => {}).then(() => enqueue());
    }

    // 如果并发数已达上限,等待任意一个任务完成后再尝试调度
    return Promise.race(executing).then(() => enqueue());
    };

    // 启动初始的并发任务(启动limit个enqueue过程)
    const pool = Array.from({ length: Math.min(limit, tasks.length) }, () => enqueue());

    // 等待所有“调度流程”完成,然后返回结果数组
    return Promise.all(pool).then(() => results);
    }

    // 使用示例
    // 模拟一个异步请求函数
    const createTask = (id, delay) => () => 
    new Promise(resolve => {
    console.log(`任务 ${id} 开始执行`);
    setTimeout(() => {
    console.log(`任务 ${id} 完成`);
    resolve(`结果-${id}`);
    }, delay);
    });

    // 创建100个任务
    const tasks = Array.from({ length: 100 }, (_, i) => createTask(i, 1000 + Math.random() * 1000));

    // 以并发数为5的方式执行
    promisePool(tasks, 5).then(results => {
    console.log('所有任务完成:', results);
    });
  1. async/await
  1.  function asyncPool(tasks, limit) {
    const results = [];
    const executing = new Set();

    for (const [index, task] of tasks.entries()) {
    // 如果当前并发数已达上限,等待其中一个任务完成
    if (executing.size >= limit) {
    await Promise.race(executing);
    }

    const promise = task().then(result => {
    results[index] = result;
    executing.delete(promise);
    });

    executing.add(promise);
    }

    // 等待所有剩余任务完成
    await Promise.all(executing);
    return results;
    }

面试官:说一下GET请求和POST请求的区别?

GET 和 POST 是 HTTP 协议中最常用的两种方法

  1. 设计目的 (语义):
    • GET 用于 获取数据。它应该是安全和幂等的。
      • 安全:意味着请求不应修改服务器上的数据(只读操作)。
      • 幂等:意味着多次执行相同的 GET 请求,产生的效果与执行一次完全一致。
    • POST 用于 提交/创建数据。它是不安全且不幂等的,通常会对服务器状态产生影响(如更新、创建资源)。
  2. 参数位置:
    • GET 参数通过 URL 传递,格式为 ?key1=value1&key2=value2。
    • POST 参数存放在 请求体(Request Body) 中。
  3. 参数大小与数据类型:
    • GET 参数有长度限制,受限于浏览器和服务器对 URL 长度的规定(通常几KB)。并且,它只能进行 URL 编码,主要传递 ASCII 字符。
    • POST 参数在理论上是没有大小限制的(实际受服务器配置约束),支持多种编码方式(如 multipart/form-data),可以传输二进制数据。
  4. 缓存机制:
    • GET 请求会被浏览器 主动缓存,因为其幂等性使得缓存结果可被安全复用。
    • POST 请求 不会被浏览器主动缓存,除非手动设置(例如通过 Cache-Control 头部)。
  5. 历史记录与书签:
    • GET 请求的完整 URL(包含参数)会被保存在浏览器历史记录中,并且可以被收藏为 书签(Bookmark)
    • POST 请求的参数不会被保留在历史记录中,也无法被直接收藏为书签。
  6. 浏览器回退行为:
    • 由于 GET 是幂等的,在浏览器中回退时,GET 请求会被无害地 重新获取,可能从缓存中加载。
    • 回退到一个 POST 请求的页面时,浏览器通常会 提示用户 是否需要重新提交表单,因为再次提交可能会产生重复操作(如创建两个订单)。
  7. 安全性(隐私性):
    • GET 参数直接暴露在 URL 上,容易被他人看到、被服务器日志记录,隐私性差,因此绝不能用于传递密码等敏感信息。
    • POST 参数在请求体中,对用户不可见,隐私性相对更好
    • 重要提示:无论是 GET 还是 POST,数据都是明文传输的。真正的安全性必须依靠 HTTPS 协议来加密整个通信过程。

http://www.dtcms.com/a/614160.html

相关文章:

  • 解决在虚拟机的ensp中启动路由器,卡0%且出现虚拟机卡死的方法
  • 网站开发项目策划书手机前端开发软件工具
  • 宁波教师巧用3D技术,打造互动几何课堂:动态观察正方体组合,让空间想象触手可及
  • Amazon VPC中Web应用无法连接数据库的安全组配置问题分析与修复
  • C++ 模板进阶:解锁泛型编程的高级玩法
  • STM32F407 GPIO深度解析:从底层架构到实战应用
  • 网站开发读什么专业做百度推广一定要有自已网站
  • 家政服务网站建设方案电商网站开发需求文档
  • SVN服务器修改ip后无法连接
  • 如何申请一个免费的网站空间建网站的意义
  • 【LeetCode刷题】和为K的子数组
  • 网站建设教程免费下载电脑平面设计软件
  • BuildingAI 二开 平台配置菜单和页面功能PRD
  • OFDM、IQ调制与AxC技术介绍
  • Linux快速安装java运行环境
  • div嵌套影响网站收录wordpress后台模版
  • 【工具】BatteryInfoView
  • RGB 颜色值与十六进制颜色码相互转换工具
  • 芜湖市网站开发直播app开发一个需要多少钱
  • 数据类型与变量
  • 如何利用LangChain1.0快速进行天气查询
  • 百度网站公司信息推广怎么做做网站很累
  • 51的DSP来了, 100MHz, STC32G144K246
  • SQL索引失效场景全汇总
  • 启闭机闸门的网站建设上海网站建设 劲晟
  • Windows系统监控利器Sysmon:从安装配置到实战攻防
  • 论文笔记(一百)GEN-0 / Embodied Foundation Models That Scale with Physical Interaction
  • 响应式设计进阶:不同屏幕尺寸下的交互优化方案
  • 指针与一维数组
  • 分销网站建设邯郸服务