【面试题】Promise只会概念远远不够,还需这17道题目巩固!
前端面试题库 (面试必备) 推荐:★★★★★
地址:前端面试题库
表妹一键制作自己的五星红旗国庆头像,超好看
在学习Promise相关题目之前,我们先做一些知识的回顾:JavaScript 是一门单线程执行的编程语言。也就是说,同一时间只能做一件事情。 JS执行机制中有同步任务
和异步任务
,执行入队优先级是前者;异步任务又分为宏任务
和微任务
,执行入队优先级是后者。我们先看一下下面例子来充分理解一下JavaScript执行机制:(如代码所示。如图所示)
console.log(1)
setTimeout(() => {console.log(2)
}, 0)
const promise = new Promise((resolve, reject) => {console.log(3);resolve(4)
})
promise.then((res) => {console.log(res)
})
// 1 3 4 2
- 同步任务:
只有前一个任务执行完毕,才能执行后一个任务
。还记得大学饭堂排队打饭例子吗,作为一个优秀的当代大学生,排队打饭遵循先来先打后来排队原则,只有前面那一个同学打完饭,你才能打。当然,你插队就另说😜。 - 异步任务:
由JavaScript 委托给宿主环境进行执行
。当异步任务执行完成后,会通知JavaScript 主线程执行异步任务的回调函数。还记得铁板烧吗,说实际的,铁板烧确实不错,细心的你有没有发现,老板里有多个锅,不可能只有一个锅,每一份铁板烧都需要时间,不然让顾客等待得花儿都谢了,你下次也不会来了,所以多个锅就代表多个任务,不需要等待一个锅烧完才去重新烧,也就是说不需要等待当前任务结束(这个任务没有那么快完成,未来某个时间点才结束,它就是异步任务),为节省时间或能耗,可以继续去执行其他任务。 - 宏任务:JavaScript自身发起。如setTimeout 、setInterval MessageChannel I/O、setImmediate(Node环境)、script(整体代码块)
- 微任务:是由宿主(浏览器、Node)发起的。MutationObserver(浏览器环境)、promise.[ then/catch/finally ]、事件队列 process.nextTick(Node环境)
- Promise:异步编程的一种解决方案,可以通俗把它当作一个容器,内部存储着某个未来才会结束的事件(通常是一个异步操作)的结果,从语法上来讲它就是一个对象,有两个特点:
有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)
- 对象状态不受外界影响。
- 状态一旦改变就不会在变,也就是说任何时候Promise都只有一种状态。
话不多说,我们直接上题目实操吧,一步步理解!
题目1️⃣:Promise没有resolve前都是同步任务。 Promise是微任务,但是Promise构造器内有同步任务,js线程会先把同步任务执行完,再去执行resolve回调。
const promise = new Promise((resolve, reject) => {console.log(1);resolve(2)console.log(3);
});
promise.then((res) => {console.log(res);
});
console.log(4, promise);// 4 fulfilled
// 1 3 4 2
题目2️⃣:当函数返回的是一个Promise实例。
const fn = () => (new Promise((resolve, reject) => {console.log(1);resolve(2)
}))
fn().then(res => {console.log(res)
})
console.log(3)
// 1 3 2
题目3️⃣:宏任务与微任务执行顺序。 定时器是宏任务,Promise是微任务,其他都是同步任务,
console.log(1)
setTimeout(() => {console.log(2)
})
Promise.resolve().then(() => {console.log(3)
})
console.log(4)
// 1 4 3 2
题目4️⃣:当微任务中嵌套宏任务、宏任务嵌套微任务、宏任务嵌套宏任务、微任务嵌套微任务时。
-
当微任务中嵌套宏任务时:由于构造器中除了resolve执行回调之外,还有其他同步任务、宏任务。
// 当微任务中嵌套宏任务 const promise = new Promise((resolve, reject) => {console.log(1);setTimeout(() => {console.log(2);resolve(3);console.log(4);}, 0);console.log(5); }); promise.then((res) => {console.log(res); }); console.log(6); // 1 5 6 2 4 3
-
当宏任务嵌套宏任务时:当发生嵌套任务时,优先处理同层级,因为程序是自上而下的,setTimeout是异步任务中的宏任务,同层级的比嵌套的先入队,所以先执行同层级。
// 宏任务嵌套宏任务 setTimeout(() => {console.log(1);setTimeout(() => {console.log(2)}, 0) }, 0) setTimeout(() => {console.log(3) }, 0) console.log(4) // 4 1 3 2
-
当宏任务嵌套微任务时:
// 宏任务嵌套微任务 setTimeout(() => {console.log(1);// 微任务Promise.resolve().then(() => {console.log(2)}) }, 0) setTimeout(() => {console.log(3) }, 0) console.log(4) // 4 1 2 3
-
微任务嵌套微任务时:同层级微任务优先执行。因为任务队列先入队都是同级别的。
// 微任务链接微任务 Promise.resolve().then(() => {console.log(1)return 2; }).then((res) => {console.log(res); }) Promise.resolve().then(() => {console.log(3) }) // 1 3 2// 微任务嵌套微任务 Promise.resolve().then(() => {console.log(1)Promise.resolve().then(() => {console.log(2)})return 3 }).then((res) => {console.log(res); }) Promise.resolve().then(() => {console.log(4) }) // 1 4 2 3
题目5️⃣:结合微任务和宏任务,灵活理解Promise三种状态。从代码中我们可以看出例子中的单纯是同步任务有2 3 4,而宏任务中的同步任务是1,当执行程序中同步任务时,微任务还没有resolve回调函数,所以promise对象都是pending状态,由于抛出错误是微任务中的宏任务,所以优先执行,然后再执行全局的setTimeout,最后promise1是fufilled状态,promise2是rejected状态。
const promise1 = new Promise((resolve, reject) => {setTimeout(() => {resolve("success");console.log(1);}, 1000);console.log(2);
});
const promise2 = promise1.then(() => {throw new Error("error!!!");
});
console.log(3, promise1);// pending
console.log(4, promise2);// pending
setTimeout(() => {console.log(5);console.log(6, promise1);// fufilledconsole.log(7, promise2);// rejected
}, 2000);
// 2 3 4 1 抛出error! 5 6 7
题目6️⃣:Promise中构造函数中的resolve或reject只有第一次执行有效。
const promise = new Promise((resolve, reject) => {resolve(1);reject("error");resolve(2);
});
promise.then(res => {console.log("then: ", res);
}).catch(err => {console.log("catch: ", err);
})
// then:1
题目7️⃣:Promise对象中的catch无视链接位置,都能捕获上层未捕捉过的错误,then3会执行因为catch会返回一个Promise,且由于这个Promise没有返回值,所以打印出来的是undefined。
const promise = new Promise((resolve, reject) => {reject("error");resolve(1);
});
promise.then(res => {console.log("then1: ", res);
}).then(res => {console.log("then2: ", res);
}).catch(err => {console.log("catch: ", err);
}).then(res => {console.log("then3: ", res);
})
// catch: error
// then3: undefined
题目8️⃣:Promise对象的链式调用的执行顺序。Promise可以链式调用,不过promise 每次调用 .then 或者 .catch 都会返回一个新的 promise,从而实现了链式调用,return 2会被包装为resolve(2)。
Promise.resolve(1)
.then(res => {console.log(res);return 2;
})
.catch(err => {return 3;
})
.then(res => {console.log(res);
});
// 1 2
题目9️⃣:注意then的第二参数错误处理与catch的区别。,两个都是处理reject状态回调结果或者是抛出的错误,如果存在第二参数,也存在catch,捕获错误是参数生效,否则就会catch生效。也可以这样理解then的第一个参数是处理成功的函数,第二个参数是处理失败的函数。如果两个都没有就会直接报错。
Promise.reject('err!!!').then((res) => {console.log('success', res)}, (err) => {console.log('error', err)}).catch(err => {console.log('catch', err)})
// error err!!!Promise.resolve()
.then(() => {throw new Error('error!!!');
})
.then(function success(res) {},function fail1(err) {console.log('fail1', err);}
)
.catch(function fail2(err) {console.log('fail2', err);
});
// fail1 Error: error!!!
题目🔟:then参数是函数,对于非函数会出现值穿透。 如果then传入的是非函数,resolve会被传到是函数的地方。
Promise.resolve(1).then(2).then(Promise.resolve(3))
.then(console.log)
// 1
题目1️⃣1️⃣:finally方法也是一个微任务。:.finally()方法不管Promise对象最后的状态如何都会执行。.finally()方法的回调函数不接受任何的参数。
function promise1() {let p = new Promise((resolve) => {console.log(1);resolve(2)})return p;
}
function promise2() {return new Promise((resolve, reject) => {reject('error')})
}
promise1().then(res => console.log(res)).catch(err => console.log(err)).finally(() => console.log('finally1'))promise2().then(res => console.log(res)).catch(err => console.log(err)).finally(() => console.log('finally2'))
// 1 2 error finally1 finally2
题目1️⃣2️⃣:async await执行机制:在async1中await后面的Promise是没有返回值的,也就是它的状态始终是pending状态,因此相当于一直在await,await,await却始终没有响应,所以就不能执行await后面的语句了。
-
async await宏任务:await强制的是当前async函数域,所以不能优先处理await后面的语句,全局同步任务可优先处理。
async function async1() {console.log(1);await async2();console.log(2); } async function async2() {setTimeout(() => {console.log(3)}, 0)console.log(4); } async1(); console.log(5) // 1 4 5 2 3
-
async await微任务:
async function async1() {console.log(1);await new Promise(resolve => {console.log(2)})// Promise没有resolve所以一直处于pendingconsole.log(3);return 'async1 end' } console.log(4) async1().then(res => console.log(res)) console.log(5) // 4 1 2 5
-
async await微任务、宏任务:
async function testSometing() {console.log(1);return 2; } async function testAsync() {console.log(3);return Promise.resolve(4); } async function test() {console.log(5);const v1 = await testSometing();console.log(v1);const v2 = await testAsync();console.log(v2);console.log(v1, v2); } test(); var promise = new Promise(resolve => {console.log(6);resolve(7); }); promise.then(val => console.log(val)); console.log(8); // 5 1 6 8 2 3 7 4 // 2 4
题目1️⃣3️⃣:理解Promise.all方法,all方需要等所有异步操作执行完后才执行回调,由于有reject状态的回调,所以没有执行then,直接执行了catch。
function runAsync(x) {const p = new Promise(r => setTimeout(() => r(x, console.log('runAsync', x)), 1000))return p
}
function runReject(x) {const p = new Promise((res, rej) => setTimeout(() => rej(`Error: ${x}`, console.log('runRejct', x)), 1000 * x))return p
}
Promise.all([runAsync(1), runReject(4), runAsync(3), runReject(2)]).then(res => console.log('then:', res)).catch(err => console.log('catch:', err))
// runAsync 1
// runAsync 3
// runRejct 2
// catch: Error: 2
// runRejct 4
问题1️⃣4️⃣:理解Promise.race方法,race获取最快的哪一个异步操作的结果。由于下面执行了一个reject状态的回调,所以没有执行then,如果没有这个runReject(0),下面例子打印的是1 result:1 2 3。
function runAsync(x) {
const p = new Promise(r =>setTimeout(() => r(x, console.log(x)), 1000)
);
return p;
}
function runReject(x) {
const p = new Promise((res, rej) =>setTimeout(() => rej(`Error: ${x}`, console.log(x)), 1000 * x)
);
return p;
}
Promise.race([runReject(0), runAsync(1), runAsync(2), runAsync(3)])
.then(res => console.log("result: ", res))
.catch(err => console.log(err));
// 0 Error:0 1 2 3
问题1️⃣5️⃣: 构造函数里resolve之前的同步任务打印3 7优先执行,然后就是first后面的全局同步任务4,注意这里与上面的嵌套微任务的区别,因为这里直接resolve(2)的话first就会完成回调函数了,但是最外层构造函数内还有一个微任务p,所以先执行。
const first = () => (new Promise((resolve, reject) => {console.log(3);let p = new Promise((resolve, reject) => {console.log(7);setTimeout(() => {console.log(5);resolve(6);console.log(p)}, 0)resolve(1);});resolve(2);p.then((arg) => {console.log(arg);});
}));
first().then((arg) => {console.log(arg);
});
console.log(4);
// 3 7 4 1 2 5 fulfilled:1
问题1️⃣6️⃣:综合Promise值穿透、宏任务、微任务、async await
const async1 = async () => {console.log(1);setTimeout(() => {console.log(2)}, 2000)await new Promise(resolve => {console.log(3)})console.log(4)return 5
}
console.log(6);
async1().then(res => console.log(res));
console.log(7);
Promise.resolve(8).then(9).then(Promise.resolve(10)).catch(11).then(res => console.log(res))
setTimeout(() => {console.log(12)
}, 1000)
//6 1 3 7 8 12 2
问题1️⃣7️⃣: Promise的状态一旦改变就无法改变。.finally的返回值如果在没有抛出错误的情况下默认会是上一个Promise的返回值。由于微任务Promise中有宏任务,并且有多个resolve,但是Promise值只能回调一个函数,所以打印了3,.finally也是一个微任务并且不接收回调函数参数,所以为undefined,然后执行微任务Promise中宏任务,接着执行then中的宏任务,此时p1状态是undefined(没有then处理)。
const p1 = new Promise((resolve) => {setTimeout(() => {resolve(1);console.log(2)}, 0)resolve(3);resolve(4);
}).then(res => {console.log(res)// 打印3setTimeout(() => {console.log(p1)}, 1000)
}).finally(res => {console.log('finally:', res)
})
// 3 finally:undefined 2 fulfilled:undefined
✍总结:其实学完这17道题目,希望各位同仁有收获,对于Promise的执行有更深理解与掌握。接下来就总结一下如何快速处理这种题目的技巧(从上到下按顺序理解):
-
🚩
先看是否同步任务
:对于非函数,先看当前语句是否是同步任务,是就先执行;对于函数,不管是同步还是异步操作,也是先执行同步任务。 -
🚩
异步任务判断是宏任务还是为微任务
:先执行微任务,后执行宏任务。 -
🚩
任务嵌套情况,灵活处理
:不管是微任务还是宏任务,先处理同级别任务,但是对于微任务有些情况特殊需要灵活理解。 -
🚩
Promise特点要重视
:- 对象状态不受外界影响;状态一旦改变就不会再变。
- then传参必须是函数,否则出现值穿透。
- 理解catch处理与then第二个参数处理。
- Promise如果没有resolve或reject,就会一直处于pending状态。
- 区分all方法与race方法。
-
🚩
理解async await
:强制执行函数体内await当前语句完毕(也相当于一个微任务),才会执行函数体内await后面的语句。
前端面试题库 (面试必备) 推荐:★★★★★
地址:前端面试题库
表妹一键制作自己的五星红旗国庆头像,超好看
相关文章:

【面试题】Promise只会概念远远不够,还需这17道题目巩固!
前端面试题库 (面试必备) 推荐:★★★★★ 地址:前端面试题库 表妹一键制作自己的五星红旗国庆头像,超好看 在学习Promise相关题目之前,我们先做一些知识的回顾:JavaScript 是一门单…...

互联网医院牌照|互联网医院牌照审批流程和材料
随着科技的不断进步和社会的发展,互联网医院已经成为了当前的热点。而互联网医院的准入门槛自然也就越来越高。如果您计划成立一个互联网医院,您需要了解申请互联网医院牌照所需要注意的方面以及申请的流程。 一、资质申请前的准备 1、立项阶段准备 在立…...

第五章:C语言的数组
文章目录 1、数组的理解2、各类数组的定义3、变长数组4、字符数组 1、数组的理解 一维数组:比如定义一个int a[3];,那么可以将其看成两部分,a【3】为①,int为②。意思就是有一个数组名字为a,里面包含3个(池࿰…...

Spring面试题3:说一说MVC框架的底层实现
该文章专注于面试,面试只要回答关键点即可,不需要对框架有非常深入的回答,如果你想应付面试,是足够了,抓住关键点 面试官:说一说MVC框架的底层实现 MVC(Model-View-Controller)是一种软件设计模式,常被用于构建用户界面和应用程序的架构。MVC框架的底层实现可以分为…...
云原生周刊:K8s 的 13 个最佳开源监控工具
开源项目推荐 Silver Surfer 该项目旨在检查 Kubernetes 对象的 API 版本兼容性,并为其提供迁移路径,以便为集群升级做好准备。 Actions Runner Controller Actions Runner Controller (ARC) 是一个 Kubernetes 操作器,可为 GitHub Actio…...
怎么克服一篇论文写作前的恐惧感?
作者 代陈锐 中国科学技术大学生命科学与医学部在读博士生,主要探究生理和病理过程中组蛋白翻译后修饰的调控机制。 1. 引言 在我们开始一篇文章的撰写时,往往不知如何下笔或是不停否认自己撰写的内容,最终的结果自然是撰写效率低而且陷入自我纠结。在这里我通过结合平时…...
Linux 安全 - Credentials
文章目录 一、简介1.1 Objects1.2 Object ownership1.3 The objective context1.4 Subjects1.5 The subjective context1.6 Actions1.7 Rules, access control lists and security calculations 二、Types of Credentials2.1 Traditional UNIX credentials2.2 Capabilities2.3 …...
网站服务器怎么部署
网站服务器怎么部署 1. 选择合适的服务器:根据网站的需求和流量,选择合适的服务器,包括硬件配置、操作系统和网络环境等。 2. 安装操作系统:根据服务器硬件配置选择合适的操作系统,并进行安装和配置,包括安…...

密码学【第一节:密码学概述】
前言 在区块链的整个体系中大量使用了密码学算法,比如用于 PoW 的哈希算法,用于完整性验证的 Merkle Tree,用于交易签名与验证的数字签名算法,用于隐私保护的零知识证明等等。 可以说密码学是保证区块链安全的基石,而区…...

Leetcode 95. 不同的二叉搜索树 II
文章目录 题目代码(9.21 首刷看解析) 题目 Leetcode 95. 不同的二叉搜索树 II 代码(9.21 首刷看解析) class Solution { public:vector<TreeNode*> generateTrees(int n) {return build(1,n);}vector<TreeNode*> bu…...

Nodejs+vue高校机房设备管理系统jt07u
开发语言 node.js 框架:Express 前端:Vue.js 数据库:mysql 数据库工具:Navicat 开发软件:VScode 集成IDE对高校机房设备管理系统统进行开发,整合系统的各个模块。 拟开发的高校机房设备管理系统通过测试,确保在最大负载的情况下…...

Purple-Pi-OH OHOS SDK编译手册
一、源码获取 1.1 源码获取 链接:百度网盘 请输入提取码 提取码:1234 $ mkdir purple-pi #将下载的ido_purple_pi_oh_ohos3.2_sdk.tgz拷贝到purple-pi $ cd purple-pi $ md5sum ido_purple_pi_oh_ohos3.2_sdk.tgz e6ca2d96aa7c628992ae0bbf4d14c2ca …...
Java高级-stream流
stream流 1.介绍2.将List转成Set3.将List转成Map4.计算求和reduce5.查找最大值max和最小值min6.Match匹配7.过滤器 filter8.分页limit 跳过skip9.数据排序 sorted 1.介绍 stream流可以非常方便与精简的形式遍历集合,实现过滤、排序等功能 2.将List转成Set stream…...

Python环境搭建
Python|环境搭建&第一个py程序 文章目录 Python|环境搭建&第一个py程序运行环境搭建验证安装是否成功安装PyCharm第一个python程序避免每次打开都进入上次关闭的项目 运行环境搭建 官网:https://www.python.org/downloads/windows/ 注意:下载过…...

JOSEF约瑟 SSJ-41B SSJ-41A 静态时间继电器 延时范围0.02-9.99s
SSJ静态时间继电器 系列型号: SSJ-11A静态时间继电器;SSJ-12A静态时间继电器; SSJ-11B静态时间继电器;SSJ-21B静态时间继电器 SSJ-21A静态时间继电器;SSJ-22A静态时间继电器 SSJ-22B静态时间继电器SSJ-42B静态时间…...
文件MultipartFile上传同时,接收复杂参数
方案一MultipartFile和dto分开 PostMapping("/uploadData") public Result<Object> uploadData(RequestParam("file") MultipartFile file,RequestPart() DataDTO dataDTO) {// 处理文件上传逻辑,如保存文件到本地或云存储// 处理接收到…...
Nginx 获取当前机器IP- Protocol- Port
Full Example Configuration | NGINX Alphabetical index of variables $server_addr:当前nginx所部署的机器 $server_port:当前监听的port server {listen 12345 udp;return ‘$server_addr:$server_port; } 参数说明示例$remote_addr$remote_user$…...

Unity丨自动巡航丨自动寻路丨NPC丨
文章目录 概要功能展示技术细节小结 概要 提示:这里可以添加技术概要 本文功能是制作一个简单的自动巡逻的NPC,随机自动寻路。 功能展示 技术细节 using UnityEngine;public class NPCController : MonoBehaviour {public float moveSpeed 5.0f; // …...

Mysql002:(库和表)操作SQL语句
目录: 》SQL通用规则说明 SQL分类: 》DDL(数据定义:用于操作数据库、表、字段) 》DML(数据编辑:用于对表中的数据进行增删改) 》DQL(数据查询:用于对表中的数…...

排水管网液位监测,排水管网液位监测方法
排水管网是城市生命线基础设施的重要组成部分,它的正常运行直接关系到城市的洪水防治、环境保护和居民生活质量。对排水管网液位进行实时监测对管理和维护排水系统稳定运行具有重要作用。那么如何对监测排水管网液位呢?本文将着重为大家详细介绍排水管网液位监测方…...

装饰模式(Decorator Pattern)重构java邮件发奖系统实战
前言 现在我们有个如下的需求,设计一个邮件发奖的小系统, 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其…...

23-Oracle 23 ai 区块链表(Blockchain Table)
小伙伴有没有在金融强合规的领域中遇见,必须要保持数据不可变,管理员都无法修改和留痕的要求。比如医疗的电子病历中,影像检查检验结果不可篡改行的,药品追溯过程中数据只可插入无法删除的特性需求;登录日志、修改日志…...

【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)
服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...
将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?
Otsu 是一种自动阈值化方法,用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理,能够自动确定一个阈值,将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...

2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面
代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口(适配服务端返回 Token) export const login async (code, avatar) > {const res await http…...

相机从app启动流程
一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...

安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(装配)
船舶制造装配管理现状:装配工作依赖人工经验,装配工人凭借长期实践积累的操作技巧完成零部件组装。企业通常制定了装配作业指导书,但在实际执行中,工人对指导书的理解和遵循程度参差不齐。 船舶装配过程中的挑战与需求 挑战 (1…...
Java数值运算常见陷阱与规避方法
整数除法中的舍入问题 问题现象 当开发者预期进行浮点除法却误用整数除法时,会出现小数部分被截断的情况。典型错误模式如下: void process(int value) {double half = value / 2; // 整数除法导致截断// 使用half变量 }此时...
Python+ZeroMQ实战:智能车辆状态监控与模拟模式自动切换
目录 关键点 技术实现1 技术实现2 摘要: 本文将介绍如何利用Python和ZeroMQ消息队列构建一个智能车辆状态监控系统。系统能够根据时间策略自动切换驾驶模式(自动驾驶、人工驾驶、远程驾驶、主动安全),并通过实时消息推送更新车…...
Web中间件--tomcat学习
Web中间件–tomcat Java虚拟机详解 什么是JAVA虚拟机 Java虚拟机是一个抽象的计算机,它可以执行Java字节码。Java虚拟机是Java平台的一部分,Java平台由Java语言、Java API和Java虚拟机组成。Java虚拟机的主要作用是将Java字节码转换为机器代码&#x…...