ES6进阶知识二
一、promise方法的案例
Promise对象通过new Promise()语法创建,它接受一个函数作为参数,该函数接受两个参数:resolve和reject。resolve表示异步操作成功,reject表示异步操作失败。
案例:异步加载图片
const loadImage = (url) => {return new Promise((resolve, reject) => {const img = new Image();img.onload = () => {resolve(img);};img.onerror = () => {reject(new Error(`Failed to load image from ${url}`));};img.src = url;});
};loadImage('https://example.com/image.jpg').then((img) => {console.log('Image loaded successfully');document.body.appendChild(img);}).catch((error) => {console.error(error.message);});
Promise.prototype.then()
then()方法接受两个可选参数:onFulfilled和onRejected,分别表示成功时和失败时的回调函数。当Promise对象的状态为fulfilled时,会立即执行onFulfilled回调函数,并将操作结果作为参数传递给该函数;当Promise对象的状态为rejected时,会立即执行onRejected回调函数,并将拒绝原因(错误信息)作为参数传递给该函数。
案例:
const p = new Promise((resolve, reject) => {resolve(1);
});p.then((res) => {console.log(res); // 输出:1return 2; // 返回值会被作为下一个then的输入},(error) => {console.log(error);}
)
.then((res) => {console.log(res); // 输出:2}
);
Promise.prototype.catch()
catch()方法是then(undefined, onRejected)的语法糖,用于捕获Promise对象被rejected时的错误信息。
案例:
const p = new Promise((resolve, reject) => {reject('error');
});p.then((res) => {console.log(res); // 不会执行
})
.catch((error) => {console.log(error); // 输出:error
});
1.1.promise.all
过程:
1.创建promise数组:首先,需要创建一个包含多个promise对象的数组,每个promise对象都代表一个异步操作。
2.调用promise.all:然后调用promise.all方法,并将这个数组作为参数传递给它。promise.all会返回一个新的promise对象
3.处理结果:
如果所有的输入promiase对象都成功解析,那么promise.all返回的promise对象也会被解析,并且它的解析值是一个数组,包含了所有输入promise对象的解析值,顺序与输入数组一致。
如果任何一个输入promise对象被拒绝,那么promise.all返回的promise对象也会被拒绝,并且它的拒绝原因与第一个被拒绝的promise对象的拒绝原因相同。
4.使用.then和.catch:可以使用.then方法来处理成功的情况,使用.catch方法来处理失败的情况
例子:同时加载多张图片
const urls = ['https://example.com/image1.jpg','https://example.com/image2.jpg','https://example.com/image3.jpg'
];const loadImage = (url) => {return new Promise((resolve, reject) => {const img = new Image();img.onload = () => {resolve(img);};img.onerror = () => {reject(new Error(`Failed to load image from ${url}`));};img.src = url;});
};Promise.all(urls.map(loadImage)).then((images) => {console.log('All images loaded successfully');images.forEach((img) => {document.body.appendChild(img);});}).catch((error) => {console.error(error.message);});
1.2.promise.race
过程:
1.创建promise数组:首先,需要创建一个包含多个promise对象的数组,每个promise对象都代表一个异步操作。
2.调用promise.race:然后调用promise.race方法,并将这个数组作为参数传递给它。promise.race会返回一个新的promise对象
3.处理结果:
promise.race只关心第一个完成的promise对象(无论是成功还是拒绝)
如果第一个完成的promise是成功解析的,那么promise.race返回的promise对象也会解析,并且它的解析值与第一个完成的promise对象的解析值相同
如果过第一个完成的promise是被拒绝的,那么promise.race返回的promise对象也会被拒绝,并且它的拒绝原因第一个被决绝的promise对象的拒绝原因相同
4.使用.then和.catch:同样,也可以使用.then方法;来处理成功的情况,使用.catch方法来处理失败的情况。
例子:同时加载多张图片,但只显示第一张加载成功的图片
const urls = ['https://example.com/image1.jpg','https://example.com/image2.jpg','https://example.com/image3.jpg'
];const loadImage = (url) => {return new Promise((resolve, reject) => {const img = new Image();img.onload = () => {resolve(img);};img.onerror = () => {reject(new Error(`Failed to load image from ${url}`));};img.src = url;});
};Promise.race(urls.map(loadImage)).then((img) => {console.log('First image loaded successfully');document.body.appendChild(img);}).catch((error) => {console.error(error.message);});
// 创建两个异步操作的Promise,其中一个会更快完成
const slowFetch = () => new Promise((resolve) => {setTimeout(() => resolve('Slow Data'), 2000);
});const fastFetch = () => new Promise((resolve) => {setTimeout(() => resolve('Fast Data'), 500);
});// 使用 Promise.race 来等待第一个异步操作完成
Promise.race([slowFetch(), fastFetch()]).then((data) => {// 由于 fastFetch 更快完成,所以这里会输出 'Fast Data'console.log(data); // 输出: 'Fast Data'}).catch((error) => {// 如果没有任何Promise被拒绝,这里的catch不会被调用console.error(error);});// 另一个例子,包含一个会被拒绝的Promise
const fetchWithTimeout = () => {return Promise.race([fetch('https://jsonplaceholder.typicode.com/posts/1') // 一个真实的fetch请求.then(response => response.json()),new Promise((_, reject) => {setTimeout(() => reject(new Error('Request timed out')), 1000); // 1秒后拒绝})]);
};// 使用 fetchWithTimeout,并处理可能的超时
fetchWithTimeout().then(post => {console.log(post); // 如果fetch请求在1秒内完成,这里会输出post数据}).catch(error => {console.error('Error:', error.message); // 如果fetch请求超时,这里会输出 'Error: Request timed out'});
在这个fetchWithTimeout的例子中,我们使用了promise.race来设置一个超时机制。如果fetch请求在1秒内没有完成,那么promise.race会返回被拒绝的promise,并且我们可以在.catch中处理这个超时错误。
promise.resolve()和promise.reject()
promise.resolve()方法返回一个已经成功状态的promise对象,并将指定的值作为参数传递给它的then方法。
promise.reject()方法返回一个已经失败状态的promise对象,并将指定原因作为参数传递给它的catch方法
案例:
// Promise.resolve()
Promise.resolve(10).then((value) => {console.log(`The value is ${value}`); // 输出:The value is 10}).catch((error) => {console.error(error.message); // 不会执行});// Promise.reject()
Promise.reject('error').then((value) => {console.log(value); // 不会执行}).catch((reason) => {console.log(reason); // 输出:error});
二、高阶语法与特性
2.1模板字符串的高级用法
本小节讲解模板字符串的嵌套、标签模板等高级用法,了解它们如何用于字符串的格式化、插值等操作。
2.1.1.模板字符串的嵌套
模板字符串允许嵌套另一个模板字符串,这在处理复杂数据结构时非常有用。例如,假设有一个包含地址信息的数组,可以使用嵌套模板字符串来生成一个HTML表格:
const addrs = [{ first: 'John', last: 'Doe' },{ first: 'Jane', last: 'Smith' }
];const tmpl = addrs => `<table>${addrs.map(addr => `<tr><td>${addr.first}</td></tr><tr><td>${addr.last}</td></tr>`).join('')}</table>
`;console.log(tmpl(addrs));
上述代码中,内部的模板字符串用于生成每一行的表格内容,外部的模板字符串则负责将这些行组合成一个完整的表格。
2.1.2.标签模板用于字符串的格式化、插值等操作
标签模板(Tagged Template)是一种特殊的函数,它允许对模板字符串进行自定义处理。标签模板函数的基本语法是在一个函数名后面紧跟一个模板字符串字面量。这个函数会接收两个参数:一个由模板字符串中的静态文本部分组成的数组,以及由模板字符串中的表达式求值结果组成的剩余参数列表。
1.字符串格式化
可以创建一个标签模板函数来格式化日期、数字或货币等。例如,以下是一个简单的标签模板函数,用于将数字格式化为货币形式:
function formatCurrency(strings, ...values) {let result = '';for (let i = 0; i < strings.length; i++) {result += strings[i];if (i < values.length) {result += '$' + values[i].toFixed(2); // 将数字格式化为两位小数的货币形式}}return result;
}const price = 123.456;
console.log(formatCurrency`The price is ${price}`); // 输出 "The price is $123.46"
2.字符串插值:
标签模板函数也可以用于字符串插值,但与普通的模板字符串插值不同,标签模板函数可以对插入的变量或表达式进行自定义处理。例如,以下是一个将字符串转换为大写的标签模板函数:
function upperCase(strings, ...values) {return strings.reduce((result, str, i) => {const value = values[i - 1] || '';return result + str + value.toUpperCase();}, '');
}const greeting = upperCase`Hello, ${'world'}!`; // 输出 "Hello, WORLD!"
3. 避免XSS攻击
在处理用户输入时,标签模板函数还可以用于避免跨站脚本攻击(XSS)。例如,可以对用户输入进行HTML转义
function escapeHTML(strings, ...values) {let result = '';for (let i = 0; i < strings.length; i++) {result += strings[i];if (i < values.length) {// 简单的HTML转义函数const escape = (html) => html.replace(/[&<>"'`=\/]/g, (s) => `&#${s.charCodeAt(0)};`);result += escape(values[i]);}}return result;
}const userInput = '<script>alert("XSS!");</script>';
console.log(escapeHTML`Safe input: ${userInput}`);
// 输出 "Safe input: <script>alert("XSS!");</script>"
三、尾调用优化
3.1.尾调用优化(Tail Call Optimization)的概念和作用
尾调用优化是编译器或解释器对函数调用的一种优化手段。当函数A的最后一步是调用另一个函数B,并且A的返回值就是B的调用结果时,这个调用就被称为尾调用。如果编译器或解释器支持尾调用优化,那么在执行尾调用时,可以只保留函数B的调用记录,而删除函数A的调用记录,因为A的调用结果已经确定并且不再需要A的调用记录。这种优化可以显著减少内存使用,避免因为递归调用过深而导致的栈溢出错误。
3.2.递归函数中的尾调用优化
在递归函数中,尾调用优化尤为重要。传统的递归调用可能会导致大量的栈空间被占用,因为每次递归调用都会创建一个新的栈帧。而尾调用优化可以确保只有一个栈帧被重复使用,从而避免了栈空间的无谓消耗。
3.3.举例说明
已计算阶乘的递归函数为例,非尾递归和尾递归的实现方式如下:
非尾递归实现:
function factorial_recursive(n) {if (n === 0) {return 1;} else {return n * factorial_recursive(n - 1); // 这里不是尾调用,因为乘法操作在调用之后}
}
在这个非尾递归的实现中,每次递归调用之后都有一个乘法操作,因此这不是一个尾调用。编译器无法对这个递归调用进行优化。
尾递归实现:
function factorial_tail_recursive(n, result = 1) {if (n === 0) {return result;} else {return factorial_tail_recursive(n - 1, n * result); // 这里是尾调用,因为调用之后没有其他操作}
}
在这个尾递归的实现中,递归调用是函数的最后一个操作,并且这个调用的返回值就是整个函数的返回值。因此,编译器可以对这个递归调用进行优化,通过重用当前栈帧来避免增加额外的栈空间。
3.4.如何应用尾调用优化
要将一个递归函数改写为尾递归函数,通常需要引入一个辅助参数来保存中间结果。这个辅助参数在每次递归调用时都会被更新,并在递归结束时返回最终结果。
例2:计算斐波那契数列
非尾递归实现:
function fibonacci_non_tail_recursive(n) {if (n <= 1) {return n;} else {return fibonacci_non_tail_recursive(n - 1) + fibonacci_non_tail_recursive(n - 2);}
}
这个非尾递归的实现导致大量的重复计算和栈空间消耗。
尾递归实现
function fibonacci_tail_recursive(n, a = 0, b = 1) {if (n === 0) {return a;} else if (n === 1) {return b;} else {return fibonacci_tail_recursive(n - 1, b, a + b);}
}
在这个尾递归的实现中,我们引入了两个辅助参数 a 和 b 来保存斐波那契数列的前两个数。每次递归调用时,我们都会更新这两个参数,并在递归结束时返回最终结果。由于递归调用是函数的最后一个操作,并且这个调用的返回值就是整个函数的返回值,因此编译器可以对这个递归调用进行优化。
四、模块化进阶
4.1.动态导入
4.1.1.基本语法
动态导入使用import()函数,该函数返回一个Promise对象。这意味着你可以使用.then()方法或async/await语法来处理导入的模块。以下是动态导入的常见写法:
1.导入整个模块:
import('./module.js').then((module) => {// 使用 module
});
2.导入模块的特定导出
import('./module.js').then(({ export1, export2 }) => {// 使用 export1 和 export2
});
4.1.2.动态导入的特点与优势
按需加载:动态导入允许你在需要时才加载模块,这有助于减少初始加载时间,提高应用性能。
代码分割:结合构建工具(如Webpack),动态导入可以实现代码分割,将代码拆分成更小的块,以便更高效地加载和执行。
条件加载:你可以根据条件动态加载不同的模块,这在实现功能切换或按需加载特定功能时非常有用。
4.1.3.动态导入的应用场景
按需加载组件:在单页面应用(SPA)中,你可以使用动态导入来按需加载组件,从而减少初始加载时间和内存占用。
条件加载模块:根据用户的操作或环境变量等条件,动态加载不同的模块以实现功能切换。
优化性能:通过代码分割和按需加载,动态导入可以显著提高应用的加载速度和性能。
4.1.4示例
使用动态导入根据条件加载不同模块
// 定义一个函数,根据不同的条件导入不同的模块
function loadModule(condition) {if (condition === 'moduleA') {return import('./moduleA.js');} else {return import('./moduleB.js');}
}// 使用 loadModule() 函数来动态导入模块
loadModule('moduleA').then((module) => {// 使用 moduleA 模块
}).catch((error) => {// 处理错误
});loadModule('moduleB').then((module) => {// 使用 moduleB 模块
}).catch((error) => {// 处理错误
});
在这个示例中,我们定义了一个loadModule函数,它根据传入的条件动态加载不同的模块。然后,我们使用loadModule函数来导入模块,并在Promise的then方法中使用相应的模块。
4.1.5.注意事项
兼容性:虽然大多数现代浏览器都支持动态导入,但在一些旧版浏览器中可能无法使用。因此,在开发过程中需要注意兼容性问题。
构建工具:为了充分利用动态导入的优势,通常需要结合构建工具(如Webpack)进行代码分割和优化。
错误处理:在使用动态导入时,需要妥善处理可能出现的错误,以确保应用的稳定性和用户体验。
4.2.循环依赖
循环依赖指的是两个或多个模块之间互相引用,形成一个闭环的依赖关系。这种依赖关系可能会导致一些潜在的问题,如模块加载顺序错误、未定义或未初始化的变量等。
4.2.1.循环依赖的定义与示例
循环依赖通常发生在以下情况:模块A依赖于模块B的导出,同时模块B也依赖于模块A的导出。这种依赖关系形成了一个闭环,可能导致模块加载和执行时的错误。
例如,有以下连个模块文件:
// a.js
import { b } from './b.js';export const a = () => {console.log('This is a.js');b();
};// b.js
import { a } from './a.js';export const b = () => {console.log('This is b.js');a();
};
在这个例子中,a.js和b.js互相引用对方,形成了一个循环依赖。
4.2.2.循环依赖的问题与影响
1.加载顺序问题:在循环依赖的情况下,模块的加载顺序变得不确定。这可能导致某些模块在还未完全初始化的情况下就被其他模块引用,从而引发错误。
2.未定义或未初始化的变量:由于加载顺序的不确定性,可能会出现某些变量在引用时还未被定义或初始化的情况。
3.性能问题:循环依赖可能导致模块加载和执行的效率降低,因为模块之间的依赖关系变得更加复杂。
4.2.3.解决循环依赖的方法
1.重构代码:通过重构代码来消除循环依赖。例如,可以将一些公共的功能或数据提取到一个新的模块中,并让其他模块都依赖于这个新模块。
2.使用异步加载:在ES6中,可以使用动态导入(import())来异步加载模块。这有助于在需要时才加载模块,从而避免循环依赖的问题。但需要注意的是,异步加载可能会增加代码的复杂性和加载时间。
3.依赖注入:通过依赖注入模式来管理模块之间的依赖关系。这有助于降低模块之间的耦合度,并使得依赖关系更加清晰和可控。
4.使用第三方库或工具:一些第三方库或工具(如Webpack的splitChunks插件)可以帮助开发者更好地管理和优化模块之间的依赖关系。
4.2.4.最佳实践与建议
1.避免循环依赖:在设计模块时,应尽量避免循环依赖的发生。通过合理的模块划分和组织,可以降低循环依赖的风险。
2.清晰的模块接口:确保每个模块都有清晰的接口和职责。这有助于其他模块更容易地理解和使用它们,并降低循环依赖的可能性。
3.使用构建工具:利用构建工具(如Webpack、Rollup等)来优化模块之间的依赖关系。这些工具可以帮助开发者更好地管理模块、减少打包文件的大小并提高加载速度。
亲爱的友友们~~~码这么多字不容易啊 给孩子点点赞叭,评论个1也成呐
当然上述内容若有遗漏或不足之处,恳请各位大佬不吝赐教,指正并帮助美化,以期更加完善。
相关文章:
ES6进阶知识二
一、promise方法的案例 Promise对象通过new Promise()语法创建,它接受一个函数作为参数,该函数接受两个参数:resolve和reject。resolve表示异步操作成功,reject表示异步操作失败。 案例:异步加载图片 const loadIma…...
大语言模型通用能力排行榜(2024年10月8日更新)
数据来源SuperCLUE 榜单数据为通用能力排行榜 排名 模型名称 机构 总分 理科 文科 Hard 使用方式 发布日期 - o1-preview OpenAI 75.85 86.07 76.6 64.89 API 2024年11月8日 - Claude 3.5 Sonnet(20241022) Anthropic 70.88 82.4…...
第六节、Docker 方式部署指南 github 上项目 mkdocs-material
一、简介 MkDocs 可以同时编译多个 markdown 文件,形成书籍一样的文件。有多种主题供你选择,很适合项目使用。 MkDocs 是快速,简单和华丽的静态网站生成器,可以构建项目文档。文档源文件在 Markdown 编写,使用单个 YAML 配置文件配置。 MkDocs—markdown项目文档工具,…...
【MySQL】MySQL中的函数之JSON_REPLACE
在 MySQL 中,JSON_REPLACE() 函数用于在 JSON 文档中替换现有的值。如果指定的路径不存在,则 JSON_REPLACE() 不会修改 JSON 文档。如果需要添加新的键值对,可以使用 JSON_SET() 函数。 基本语法 JSON_REPLACE(json_doc, path, val[, path,…...
【大数据学习 | HBASE高级】hbase的API操作
首先引入hbase的依赖 <dependencies><dependency><groupId>org.apache.hbase</groupId><artifactId>hbase-server</artifactId><version>2.4.13</version></dependency><dependency><groupId>org.slf4j<…...
C++(Qt)软件调试---内存泄漏分析工具MTuner (25)
C(Qt)软件调试—内存泄漏分析工具MTuner (25) 文章目录 C(Qt)软件调试---内存泄漏分析工具MTuner (25)[toc]1、概述🐜2、下载MTuner🪲3、使用MTuner分析qt程序内存泄漏🦧4、相关地址ὁ…...
python核心语法
目录 核⼼语法第⼀节 变量0.变量名规则1.下⾯这些都是不合法的变量名2.关键字3.变量赋值4.变量的销毁 第⼆节 数据类型0.数值1.字符串2.布尔值(boolean, bool)3.空值 None 核⼼语法 第⼀节 变量 变量的定义变量就是可变的量,对于⼀些有可能会经常变化的数据&#…...
MATLAB用CNN-LSTM神经网络的语音情感分类深度学习研究
全文链接:https://tecdat.cn/?p38258 在语音处理领域,对语音情感的分类是一个重要的研究方向。本文将介绍如何通过结合二维卷积神经网络(2 - D CNN)和长短期记忆网络(LSTM)构建一个用于语音分类任务的网络…...
智能网页内容截图工具:AI助力内容提取与可视化
我们每天都会接触到大量的网页内容。然而,如何从这些内容中快速提取关键信息,并有效地进行整理和分享,一直是困扰我们的问题。本文将介绍一款我近期完成的基于AI技术的智能网页内容截图工具,它能够自动分析网页内容,截…...
Axure设计之文本编辑器制作教程
文本编辑器是一个功能强大的工具,允许用户在图形界面中创建和编辑文本的格式和布局,如字体样式、大小、颜色、对齐方式等,在Web端实际项目中,文本编辑器的使用非常频繁。以下是在Axure中模拟web端富文本编辑器,来制作文…...
【MyBatis源码】深入分析TypeHandler原理和源码
🎮 作者主页:点击 🎁 完整专栏和代码:点击 🏡 博客主页:点击 文章目录 原始 JDBC 存在的问题自定义 TypeHandler 实现TypeHandler详解BaseTypeHandler类TypeReference类型参考器43个类型处理器类型注册表&a…...
号卡分销系统,号卡系统,物联网卡系统源码安装教程
号卡分销系统,号卡系统,物联网卡系统,,实现的高性能(PHP协程、PHP微服务)、高灵活性、前后端分离(后台),PHP 持久化框架,助力管理系统敏捷开发,长期持续更新中。 主要特性 基于Auth验证的权限…...
常用命令之LinuxOracleHivePython
1. 用户改密 passwd app_adm chage -l app_adm passwd -x 90 app_adm -> 执行操作后,app_adm用户的密码时间改为90天有效期--查看该euser用户过期信息使用chage命令 --chage的参数包括 ---m 密码可更改的最小天数。为零时代表任何时候都可以更改密码。 ---M 密码…...
从dos上传shell脚本文件到Linux、麒麟执行报错“/bin/bash^M:解释器错误:没有那个文件或目录”
[rootkylin tmp]#./online_update_wars-1.3.0.sh ba51:./online_update_wars-1.3.0.sh:/bin/bash^M:解释器错误:没有那个文件或目录 使用scp命令上传文件到麒麟系统,执行shell脚本时报错 “/bin/bash^M:解释器错误:没有那个文件或目录” 解决方法: 执行…...
使用 Go 实现将任何网页转化为 PDF
在许多应用场景中,可能需要将网页内容转化为 PDF 格式,比如保存网页内容、生成报告、或者创建网站截图。使用 Go 编程语言,结合一些现有的库,可以非常方便地实现这一功能。本文将带你一步一步地介绍如何使用 Go 语言将任何网页转换…...
文件操作和IO
目录 一. 文件预备知识 1. 硬盘 2. 文件 (1) 概念 (2) 文件路径 (3) 文件类型 二. 文件操作 1. 文件系统操作 [1] File常见的构造方法 [2] File的常用方法 [3] 查看某目录下所有的目录和文件 2. 文件内容操作 (1) 打开文件 (2) 关闭文件 (3) 读文件 (4) 写文件 …...
【C++滑动窗口】1248. 统计「优美子数组」|1623
本文涉及的基础知识点 C算法:滑动窗口及双指针总结 LeetCode1248. 统计「优美子数组」 给你一个整数数组 nums 和一个整数 k。如果某个连续子数组中恰好有 k 个奇数数字,我们就认为这个子数组是「优美子数组」。 请返回这个数组中 「优美子数组」 的数…...
C语言导航 4.1语法基础
第四章 顺序结构程序设计 第一节 语法基础 语句概念 语句详解 程序详解 4.1.1语句概念 说明:构成高级语言源程序的基本单位。 特征:在C语言中语句以分号作为结束标志。 分类: (1)简单语句:空语句、…...
使用 Python 和 Py2Neo 构建 Neo4j 管理脚本
Neo4j 是一个强大的图数据库,适合处理复杂的关系型数据。借助 Python 的 py2neo 库,我们可以快速实现对 Neo4j 数据库的管理和操作。本文介绍一个功能丰富的 Python 脚本,帮助用户轻松管理 Neo4j 数据库,包含启动/停止服务、清空数…...
Centos 7 安装wget
Centos 7 安装wget 最小化安装Centos 7 的话需要上传wget rpm包之后再路径下安装一下。rpm包下载地址(http://mirrors.163.com/centos/7/os/x86_64/Packages/) 1、使用X-ftp 或者WinSCP等可以连接上传的软件都可以首先连接服务器,这里我用的…...
Oracle查询表空间大小
1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...
基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容
基于 UniApp + WebSocket实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...
《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》
在注意力分散、内容高度同质化的时代,情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现,消费者对内容的“有感”程度,正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中࿰…...
【Go】3、Go语言进阶与依赖管理
前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课,做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程,它的核心机制是 Goroutine 协程、Channel 通道,并基于CSP(Communicating Sequential Processes࿰…...
unix/linux,sudo,其发展历程详细时间线、由来、历史背景
sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...
均衡后的SNRSINR
本文主要摘自参考文献中的前两篇,相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程,其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt 根发送天线, n r n_r nr 根接收天线的 MIMO 系…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
docker 部署发现spring.profiles.active 问题
报错: org.springframework.boot.context.config.InvalidConfigDataPropertyException: Property spring.profiles.active imported from location class path resource [application-test.yml] is invalid in a profile specific resource [origin: class path re…...
初探Service服务发现机制
1.Service简介 Service是将运行在一组Pod上的应用程序发布为网络服务的抽象方法。 主要功能:服务发现和负载均衡。 Service类型的包括ClusterIP类型、NodePort类型、LoadBalancer类型、ExternalName类型 2.Endpoints简介 Endpoints是一种Kubernetes资源…...
JS设计模式(4):观察者模式
JS设计模式(4):观察者模式 一、引入 在开发中,我们经常会遇到这样的场景:一个对象的状态变化需要自动通知其他对象,比如: 电商平台中,商品库存变化时需要通知所有订阅该商品的用户;新闻网站中࿰…...
