Promise

介绍和基本使用

Promise是ES6引入的异步编程的新解决方案,主要用来解决回调地狱问题。语法上 Promise是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果。

  1. Promise构造函数:new Promise()

  2. Promise.prototype.then方法

  3. Promise.prototype.catch方法

//创建实例
const p = new Promise(function (resolve, reject) {//模拟主体业务代码setTimeout(() => {//let data = "成功获取数据库中的数据";//如果获取数据成功,执行resolve()函数,并将返回数据作为参数传入//resolve(data);let data = "获取失败";//如果获取数据失败,执行reject()函数,并将返回数据作为参数传入reject(data);}, 1000);
});
//调用promise实例
p.then(function (value) {//执行resolve函数执行的方法//...
}, function (reason) {//执行reject()函数执行的方法//...
});

这种写法好处在于代码简洁,避免了回调地狱问题。

Promise.prototype.then

调用then方法,then方法的逐回结果是 Promise对象,对象状态由回调函数的执行结果决定。

  1. 如果回调函数中返回的结果是非promise 类型的属性,状态为成功,返回值为对象的成功的值.
  2. 如果回调函数中返回的结果是promise 类型的属性,状态根据then方法内部Promise返回的状态决定。
  3. 如果直接抛出错误,返回值也是promise类型的,值为抛出错误的值。
//创建实例
const p = new Promise(function (resolve, reject) {//模拟主体业务代码setTimeout(() => {//let data = "成功获取数据库中的数据";//resolve(data);let data = "获取失败";reject(data);}, 1000);
});
//调用promise实例
const result = p.then(function (value) {//1.非promise类型的属性return 'iloveyou';//2.是 promise对象return new Promise((resolve, reject) => {// resolve('ok');reject('error ');});//3.抛出错误throw new Error("出错啦!");
}, function (reason) {console.warn(reason);
});
console.log(result);

由于promise返回的是promise类型,所以可以进行链式调用

const fs = require('fs');const p = new Promise(function (resolve, reject) {fs.readFile("./source/为学.md", function (err, data) {if (err) reject(err);resolve(data);});
});p.then(value => {return new Promise((resolve, reject) => {fs.readFile("./source/为学1.md", function (err, data) {resolve([value, data]);});});
}).then(value => {return new Promise((resolve, reject) => {fs.readFile("./source/为学2.md", function (err, data) {value.push(data);return resolve(value);});});
}).then(value => {console.log(value.join('\r\n'));
});
Promise.prototype.catch

通过cache方法可以指定Promise发生错误时的回调。

promise-ajax
const p = new Promise(function (resolve, reject) {const xhr = new XMLHttpRequest();xhr.open('GET', 'https://layuion.com/static/json/table/user.json?page=1&limit=10');xhr.send();xhr.onreadystatechange = function () {if (xhr.readyState == 4) {if (xhr.status >= 200 && xhr <= 400) {resolve(xhr.response);} else {reject('获取失败');}}};
});
p.then(function (value) {console.log(value);
}, function (reason) {console.log(reason);
})

set

ES6提供了新的数据结构 set(集合)。它类似于数组,但成员的值都是唯一的(声明时即使有重复,也会去重)。集合实现了Iterator接口,所以可以使用扩展运算符和for ...of...进行遍历。

集合的属性和方法

size 返回集合的元素个数

add 增加一个新元素,返回当前集合

delete 删除元素,返回boolean值

has 检测集合中是否包含某个元素,返回boolean值

//声明集合并赋值
let s1 = new Set(['猪', '狗', '牛', '羊', '狗']);
console.log(s1); //Set(4) {'猪', '狗', '牛', '羊'}
//长度
console.log(s1.size); //4
//添加
s1.add('猫');
console.log(s1); //Set(5) {'猪', '狗', '牛', '羊', '猫'}
//删除
s1.delete('牛');
console.log(s1); //Set(4) {'猪', '狗', '羊', '猫'}
//has
console.log(s1.has('猫')) //true
console.log(s1.has('鸡')) //false
//清空
s1.clear();
console.log(s1);Set(0) {size: 0}
//遍历
for (const v of s1) {console.log(v);
}
集合实践
//集合实践
let a1 = [1, 2, 3, 5, 5, 6, 7, 8, 6, 5];
console.log(a1); //[1, 2, 3, 5, 5, 6, 7, 8, 6, 5]
//去重
let unq = [...new Set(a1)];
console.log(unq);//[1, 2, 3, 5, 6, 7, 8]
//交集
let a2 = [4, 5, 6, 9, 6, 4, 3];
const result = [...new Set(a1)].filter(item => new Set(a2).has(item));
console.log(result); //[3, 5, 6]
//并集
console.log([...new Set([...a1, ...a2])]);
//差集-> a1 和 a2取差集意思是a1里面有,a2没有的数据; 也就是交集的取反
console.log([...new Set(a1)].filter(item => !new Set(a2).has(item))); //[1, 2, 7, 8]

map

ES6提供了Map数据结构。它类似于对象,也是键值对的集合。但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。Map也实现了iterator接口,所以可以使用「扩展运算符』和「 for…of…』进行遍历。

Map的属性和方法:

size 返回Map的元素个数,

set 增加一个新元素,返回当前Map

get 返回键名对象的键值

has 检测Map 中是否包含某个元素,返回boolean值

clear清空集合,返回undefined

//声明map
let m1 = new Map();
//添加
m1.set('team', 'IG');
m1.set('jiaolian', 'ssss');
m1.set('lpl', function () {console.log('IG电子竞技!');
})
let boos = {'boos': '王思聪'
}
m1.set(boos, {'上单': 'the shy','打野': 'ning','中单': 'rookie','adc': 'jacklove','辅助': 'baolan'
});
//size
console.log(m1.size);
//删除
m1.delete('jiaolian');
//获取
console.log(m1.get('team'));
console.log(m1.get('lpl'));
console.log(m1.get(boos));
//清空
m1.clear();

WeakMap

WeakMap 对象是一组键/值对的集合,其中的键是弱引用的。其键必须是对象,而值可以是任意的。它的键被弱保持,也就是说,当其键所指对象没有其他地方引用的时候,它会被 GC 回收掉。

为什么使用weakmap?

在 JavaScript 里,map API 可以 通过使其四个 API 方法共用两个数组(一个存放键,一个存放值)来实现。给这种 map 设置值时会同时将键和值添加到这两个数组的末尾。从而使得键和值的索引在两个数组中相对应。当从该 map 取值的时候,需要遍历所有的键,然后使用索引从存储值的数组中检索出相应的值。

但这样的实现会有两个很大的缺点:

  1. 首先赋值和搜索操作都是 O(n) 的时间复杂度(n 是键值对的个数),因为这两个操作都需要遍历全部整个数组来进行匹配。

    简单来说就是赋值和搜索都会遍历整个数组,时间复杂度都是O(n)

  2. 另外一个缺点是可能会导致内存泄漏,因为数组会一直引用着每个键和值。这种引用使得垃圾回收算法不能回收处理他们,即使没有其他任何引用存在了。

相比之下,WeakMap它的键被弱保持,也就是说,当其键所指对象没有其他地方引用的时候,它会被 GC 回收掉。WeakMap提供的接口与Map相同。

Map对象不同的是,WeakMap的键是不可枚举的。不提供列出其键的方法。列表是否存在取决于垃圾回收器的状态,是不可预知的。

class类

ES6提供了更接近传统语言的写法,引入了Class(类)这个概念,作为对象的模板。通过class关键字,可以定义类。基本上,ES6的class可以看作只是一个语法糖,它的绝大部分功能,ES5都可以做到,新的 class 写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。

/*--------------------之前es5实现类的方法举例------------------------*/
//手机
function Phone(brand, price) {this.brand = brand;this.price = price;
}
//添加方法
Phone.prototype.call = function () {console.log("我可以打电话!!");
}
//实例化对象
let Huawei = new Phone('华为', 5999);
Huawei.call();
console.log(Huawei);
/*--------------------es6实现类------------------------*/
class shouji {//构造方法名字不能修改constructor(brand, price) {this.brand = brand;this.price = price;}call() {console.log("我可以打电话!!");}
}
let onePlus = new shouji('1+', 1999);
console.log(onePlus);
onePlus.call();

同一作用域的类名和函数名不能相同,例如上述代码的类名就不能命名为Phone。

类中构造方法不是必须要有。

静态成员
function Phone() { } //表示函数对象phone,相当于面向对象里面的类。
//给函数对象添加属性,它的name属性只属于Phone对象。相当于面向对象里面的静态属性
Phone.name = '手机';
//给函数对象添加方法。它的change方法只属于Phone对象相当于面向对象里面的静态方法
Phone.change = function () {console.log("我可以改变世界");
}
//访问函数对象属性和方法
console.log(Phone.name);
console.log(Phone.change);//可以通过函数对象的prototype属性给实例对象添加方法和属性
Phone.prototype.size = '5.5inch';
let nokia = new Phone(); //实例化一个对象
console.log(nokia.size); //5.5inch
//undefined 实例化对象和函数对象不相同。所以不能访问。
console.log(nokia.name);
console.log(nokia.change());//caught TypeError: nokia.change is not a function

es6中写法

class Phone{//静态属性static name ='手机';//只能通过类名访问static change(){ //只能通过类名访问console.log("我可以改变世界");}
}
let nokia = new Phone();
console.1og(nokia.name);
console.log(Phone.name);
继承

es5里实现继承

function Phone(brand, price) {this.brand = brand;this.price = price;
}
Phone.prototype.call = function () {console.log("我可以打电话");
}
//智能手机
function SmartPhone(brand, price, color, size) {Phone.call(this, brand, price);this.color = color;this.size = size;
}
//设置子级构造函数的原型
SmartPhone.prototype = new Phone;
SmartPhone.prototype.constructor = SmartPhone;//矫正,不加也可以
//声明子类的方法
SmartPhone.prototype.photo = function () {console.log("我可以拍照")
}
SmartPhone.prototype.playGame = function () {console.log("我可以玩游戏");
}
const chuizi = new SmartPhone('锤子', 2499, '黑色', '5.5inch ');
console.log(chuizi);

es6里面类的继承

class Phone {constructor(brand, price) {this.brand = brand;this.price = price;}call() {console.log('打电话')}
}class SmartPhone extends Phone {constructor(brand, price, color, size) {super(brand, price);this.color = color;this.brand = brand;}photo() {console.log("我可以拍照");}playGame() {console.log('我可以玩游戏');}
}
let xiaomi = new SmartPhone('小米', '799', '粉色', '70inch');
console.log(xiaomi);

es6中只允许继承一个类。

es6类中普通的方法中不允许调用super方法

重写

子类中可以声明同父类名称相同的方法。

getter和setter

getter:可以对类属性绑定一个函数,当调用这个属性的时候,这个函数被执行,这个函数的返回值就是这个属性的值。通常对对象的动态属性进行封装。

setter:可以对类属性绑定一个函数,当设置这个属性的时候,这个函数被执行。可以对属性的合法性进行判断

class Phone {//这里的price为类Phone的属性,后边的分别是getter和setter绑定的方法get price() {console.log('get price')return 90;}set price(price) {console.log("set price");}
}
let p = new Phone();
console.log(p.price);//get price 90
p.price = 100;//set price

数值扩展

Number.EPSILON

Number.EPSILON是JavaScript表示的最小精度。

EPSILON属性的值接近于2.2204460492503130808472633361816E-16

通常用于两个数字进行比较,如果结果比Number.EPSILON小或等于这个数,就认为这两个数字相等。

function equal(a, b) {if (Math.abs(a - b) < Number.EPSILON) {return true;} else {return false;}
}
console.log(0.1 + 0.2 === 0.3); //false
console.log(equal(0.1 + 0.2, 0.3)) //true

二进制和八进制

let b = 0b1010; //二进制
let o = 0o777; //八进制
let d = 100; //十进制
let x= 0xff; //16进制

Number.isFinite()

检测一个数值是否为有限数

console.log(Number.isFinite(100)); //true
console.log(Number.isFinite(100/0)); //false
console.log(Number.isFinite(Infinity));//false

Number.isNaN()

Number.isNaN()检测一个数值是否为NaN

Number.parseInt() Number.parseFloat()

字符串转整数

Number.isInteger()

判断一个数是否为整数

Math.trunc()

将数字的小数部分抹掉

Math.sign()

判断一个数到底为正数、负数还是零

对象的方法扩展

object.is()

判断两个值是否完全相等。和===略有不同,判断NaN的时候不一样。

console.log(Object.is(120,120));//true
console.log(Object.is(NaN,NaN));//true
console.log(NaN === NaN);//false

Object.assign()

对象的合并。如果合并的对象中有相同的属性或方法,后边的会覆盖前边的属性或方法。

get或set原型对象

Object.setPrototype0f 设置原型对象

Object.getPrototypeof 获取原型对象

模块化

模块化是指将一个大的程序文件,拆分成许多小的文件,然后将小文件组合起来。

模块化的好处

防止命名冲突

代码复用

高维护性

模块化规范产品

ES6 之前的模块化规范有:

CommonJs规范 => NodeJS、Browserify产品

AMD规范 => requireJs产品

CMD规范 => seaJs产品

ES6模块化语法

模块功能主要由两个命令构成: export和 import。

export命令用于规定模块的对外暴露接口。

/*---./js/m1.js---*/
//分别暴露
export let s = "测试模块";
export function change() {console.log('用心改变世界');
}

上边的使用export分别将schange暴露。还有以下两种暴露方式:

  • 统一暴露:在最底部写入一下代码export {s, change};

  • 默认暴露:default里面可以跟任意数据,对象居多。这种方式使用的时候就要多加个default,例如:m1.default.school

    //默认暴露
    export default {s: "测试模块',change: function(){console.log("我们可以改变你!!");}
    }
    

import命令用于输入其他模块提供的功能

import * as m1 from "./js/m1.js";
console.log(m1);

上边的代码使用的是通用导入方式,还有以下两种导入方式:

  • 解构赋值形式

    import {s, change} from "./js/m1.js";
    import {s as guigu, change} from "./js/m2.js"; //与第一个s重名,可以使用as命名别名
    import {default as m3} from " ./js/m3.js";
    
  • 简便形式,只能针对默认暴路

    import m3 from "./js/m3.js";
    console.log(m3);
    

一般引入模块都是放在一个入口文件里面如:app.js, 在html中使用时候引入这个文件就可以了

<script src="./src/js/app.js" type="module"></script> 注意:type="module".

在js文件中只要使用了import语句,不管import之间是否有javascript语句,都会按import顺序先执行import的语句

es6模块化代码转换

由于es6语法对所有的浏览器都都不一定支持,所以考虑到兼容性,需要将es6模块代码转换成es5代码。

  1. 安装工具 babel-cli(babel客户端命令行) babel-preset-env(babel环境) browserify(项目中一般使用webpack打包)

  2. 使用命令npx babel src/js -d dist/js --presets=babel-preset-env,如果全局安装babel,可以直接使用babel命令:babel src/js -d dist/js --presets=babel-preset-env. 命令的格式:

    [npx] babel 要转换文件路径 -d 转换完成后要存储的文件路径 --presets=babel-preset-env

  3. 打包:npx browserify dist/js/app.js -o dist/bundle.js

打包完成后就可以在html引入了。每次更改都需要进行上述2、3步操作。

proxy

Proxy 对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)。proxy 是javascript的内置对象,在es6中被引入。

语法
const p = new Proxy(target, handler)
参数

target : 要使用 Proxy 包装的目标对象(引用类型:对象,数组,函数,map, set, 甚至另一个代理)。

handler : 一个通常以函数作为属性的对象,各属性中的函数分别定义了在执行各种操作时代理 p 的行为。

let person = {name: "John",age: 21,
};const p = new Proxy(person, {/*** 拦截读取属性* @param target 目标对象* @param property 被获取的属性名。* @param receiver Proxy 或者继承 Proxy 的对象*/get(target, property, receiver) {},/*** 拦截赋值属性* @param target 目标对象* @param property 被设置的属性名。* @param value 属性值* @param receiver Proxy 或者继承 Proxy 的对象* @returns boolean*/set(target, property, value, receiver) {return true;},/*** 拦截方法调用* @param target 目标对象(函数)* @param thisArg 被调用时的上下文对象* @param argumentsList 被调用时的参数数组。* apply方法可以返回任何值。*/apply(target, thisArg, argumentsList) {},/*** 用于拦截 new 操作符* @param target 目标对象* @param argumentsList constructor 的参数列表* @param newTarget 最初被调用的构造函数* construct 方法必须返回一个对象。*/construct(target, argumentsList, newTarget) {return {};},/*** 用于拦截 in 操作符* @param target 目标对象。* @param prop 需要检查是否存在的属性。* has 方法返回一个 boolean 属性的值。*/has(target, prop) {return true;},/*** 法用于拦截 Reflect.ownKeys()* @param target 目标对象*/ownKeys(target) {return Reflect.ownKeys(target);},/*** 用于拦截对对象属性的 delete 操作。* @param target 目标对象。* @param property 待删除的属性名。* @returns boolean*/deleteProperty(target, property) {return true;},
});

Reflect

Reflect 是一个内置的对象,它提供拦截 JavaScript 操作的方法。这些方法与 proxy handler (en-US) 的方法相同。Reflect 不是一个函数对象,因此它是不可构造的。反射,就是将代理的内容反射出去。

与大多数全局对象不同 Reflect 并非一个构造函数,所以不能通过 new 运算符对其进行调用,或者将 Reflect 对象作为一个函数来调用。Reflect 的所有属性和方法都是静态的

注意:Reflect的静态方法是直接使用的

const p = new Proxy(person, {/*** 拦截读取属性* @param target 目标对象* @param property 被获取的属性名。* @param receiver Proxy 或者继承 Proxy 的对象*/get(target, property, receiver) {if (target.age <= 15) {return Reflect.get(target, property, receiver); //直接使用和对象操作一样} else {return "John成年了!!!";}},
静态方法
Reflect.apply(target, thisArgument, argumentsList)
对一个函数进行调用操作,同时可以传入一个数组作为调用参数。和 Function.prototype.apply() 功能类似。Reflect.construct(target, argumentsList[, newTarget])
对构造函数进行 new 操作,相当于执行 new target(...args)。Reflect.deleteProperty(target, propertyKey)
作为函数的delete操作符,相当于执行 delete target[name]。Reflect.get(target, propertyKey[, receiver])
receiver可以理解为上下文this对象
获取对象身上某个属性的值,类似于 target[name]。Reflect.getPrototypeOf(target)
类似于 Object.getPrototypeOf()。Reflect.has(target, propertyKey)
判断一个对象是否存在某个属性,和 in 运算符 的功能完全相同。Reflect.isExtensible(target)
类似于 Object.isExtensible().Reflect.ownKeys(target)
返回一个包含所有自身属性(不包含继承属性)的数组。(类似于 Object.keys(), 但不会受enumerable 影响).Reflect.preventExtensions(target)
类似于 Object.preventExtensions()。返回一个Boolean。Reflect.set(target, propertyKey, value[, receiver])
将值分配给属性的函数。返回一个Boolean,如果更新成功,则返回true。

在面向对象中,反射的三种用法:1、查看元数据。2、动态创建对象。3、动态调用方法。

示例

模拟mobx

const list: Set<Function> = new Set();
const autorun = (cb: Function) => {list.add(cb);
};
const observable = <T extends object>(target) => {return new Proxy(target, {set(target, p, newValue, receiver) {const result = Reflect.set(target, p, newValue, receiver);list.forEach((fn) => fn());return result;},});
};
const dog = observable({ name: "阿黄", age: 1 });
autorun(() => {console.log("change");
});dog.name = "阿绿"; //change
dog.age = 2; //change

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/912560.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/912560.shtml
英文地址,请注明出处:http://en.pswp.cn/news/912560.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java:如何用 JDBC 连接 TDSQL 数据库

要使用JDBC连接TDSQL数据库&#xff08;腾讯云分布式数据库&#xff0c;兼容MySQL协议&#xff09;&#xff0c;请按照以下步骤编写Java程序&#xff1a; 1. 添加MySQL JDBC驱动依赖 在项目的pom.xml中添加依赖&#xff08;Maven项目&#xff09;&#xff1a; <dependenc…

2025年四川省高考志愿填报深度分析与专业导向策略报告——基于599分/24000位次考生-AI

2025年四川省高考志愿填报深度分析与专业导向策略报告——基于599分/24000位次考生 摘要 本报告旨在为预估高考成绩599分、全省物理类位次在24,000名左右的2025年四川考生&#xff0c;提供一份兼具科学性、前瞻性与专业深度的志愿填报策略方案。报告严格遵循“位次法”为核心…

spring boot项目整合百度翻译

本片文章教大家怎样在spring boot项目中引入百度翻译&#xff0c;并且优雅的使用百度翻译。 首先&#xff0c;我们要了解为什么要使用翻译插件。为了支持多语言的国际化&#xff1b; 目前市面上最常见的后端国际化就是在resource资源目录下设置多个语言文档&#xff0c;这些文…

凌晨2点自动备份mysql 数据库,mysql_backup.sh

1、编写备份脚本&#xff1a;vim mysql_backup.sh #!/bin/bash DATE$(date %Y%m%d_%H%M%S) BACKUP_DIR"/data/mysql/backup" USER"backup_user" PASSWORD"backup**"# 逻辑备份所有数据库 mysqldump -u$USER -p$PASSWORD eblp | gzip > $BA…

Linux系统之Tomcat服务

目录 一、Tomcat概述 1、Tomcat介绍 2、Tomcat历史 二、Tomcat原理分析 1、Http工作原理 2、Tomcat整体架构 3、Coyote连接器架构 4、Catalina容器架构 5、Jasper处理流程 6、JSP编译过程 7、Tomcat启动流程 8、Tomcat请求处理流程 三、Tomcat安装与配置 1、单实…

FPGA芯片的供电

FPGA芯片的供电 文章目录 FPGA芯片的供电1. 外部端口供电机制2. 内部逻辑供电机制3. 专有电路供电机制4. 电源稳定性讨论总结 1. 外部端口供电机制 FPGA是专门用于数字系统设计的芯片&#xff0c;能够正确、可靠、高效地和外界其他数字电路进行通信是FPGA芯片必备的一个功能。…

构建可无限扩展的系统:基于 FreeMarker + 存储过程 + Spring Boot 的元数据驱动架构设计

在构建面向多行业、多客户的大型业务系统时&#xff0c;系统的灵活性与扩展能力成为架构设计的核心目标。传统硬编码的开发方式在面对高频变化、复杂组合查询、多租户自定义字段时&#xff0c;往往难以适应。 为了解决上述问题&#xff0c;我们提出一种 以 FreeMarker 脚本托管…

2-深度学习挖短线股-3-训练数据计算

2-3 合并输入特征 首先定义了数据预处理函数&#xff0c;将连续 n 天的 K 线数据&#xff08;如开盘价、收盘价、成交量等&#xff09;合并为一行特征&#xff0c;同时保留对应的目标标签&#xff08;buy 列&#xff0c;表示是否应该买入&#xff09;&#xff1b;然后读取股票代…

SpringMVC系列(四)(请求处理的十个实验(下))

0 引言 作者正在学习SpringMVC相关内容&#xff0c;学到了一些知识&#xff0c;希望分享给需要短时间想要了解SpringMVC的读者朋友们&#xff0c;想用通俗的语言讲述其中的知识&#xff0c;希望与诸位共勉&#xff0c;共同进步&#xff01; 本系列会持续更新&#xff01;&…

产线通信“变形记”:PROFIBUS-DP与ETHERNET/IP的食品饮料跨界融合

在食品饮料加工行业&#xff0c;为实现不同设备间高效通信&#xff0c;JH-PB-EIP疆鸿智能PROFIBUS DP转ETHERNET/IP网关发挥着关键作用。西门子PLC常采用PROFIBUS DP协议&#xff0c;而码垛机器人等设备多使用ETHERNET/IP协议&#xff0c;网关成为连接二者的桥梁。 将DP作为从站…

设计模式-观察者模式(发布订阅模式)

一、需要的类 一个发布类&#xff1a;里面一个是别人需要订阅的属性&#xff0c;以及用于存储订阅者的list&#xff0c;attach方法是往list集合里面添加元素&#xff0c;notifyObservers通知方法&#xff0c;也就是循环调用订阅者里面的一个方法&#xff0c;这个notifyObserve…

Linux测试是否能联网

ping百度看是否有返回包&#xff1a; ping www.baidu.com ping -c可以通过参数提前设置发送的包数量&#xff1a; ping -c 4 www.baidu.com 终止ping快捷键&#xff1a; 按下 Ctrl C&#xff1a;立即终止ping进程&#xff0c;并显示统计信息。按下 Ctrl Z&#xff1a;将进…

TOGAF® 架构分区:优秀架构的秘密

TOGAF &#xff08;The Open Group架构框架&#xff09;已成为企业架构事实上的全球标准, 是世界上使用最广泛的企业架构框架。 它为企业 IT 架构的设计、规划、实施和管理提供了一套全面的方法和工具。但是&#xff0c;即使是经验丰富的架构师也经常会忽略 TOGAF 中隐藏的宝…

如何让视频在特定的网站上播放/禁止播放?(常见的视频防盗链技术之一)

一、需求背景 在各行各业中,不论是教育、贸易还是医疗领域,视频内容都存在被盗用的风险。为加强视频安全性,我们可以采取特殊设置措施,例如限制视频仅在高安全性网站播放,或屏蔽高风险网站。那么,具体有哪些方法可以有效保护视频安全呢? 二、需求解决 通过OVP防盗链技…

如何调鼠标的灵敏度 快速调节超简单

鼠标灵敏度是指鼠标在移动时&#xff0c;指针在屏幕上移动的速度。适当的鼠标灵敏度不仅能够提高工作效率&#xff0c;还能减少手部疲劳&#xff0c;优化游戏体验。那么不同的使用场景&#xff0c;鼠标灵敏度怎么调呢&#xff1f;本文将详细探讨如何调整鼠标灵敏度&#xff0c;…

基于单次常规脑MRI的深度学习检测多发性硬化症急性和亚急性病变活动性|文献速递-最新论文分享

Title 题目 Deep learning detection of acute and sub-acute lesion activity from single-timepoint conventional brain MRI in multiple sclerosis 基于单次常规脑MRI的深度学习检测多发性硬化症急性和亚急性病变活动性 01 文献速递介绍 多发性硬化症&#xff08;MS&am…

CloudFormation 实现 GitHub Actions OIDC 与 AWS ECR 的安全集成

引言:现代 CI/CD 的安全挑战 在容器化应用部署流程中,传统长期凭证管理已成为主要安全痛点。本文将详细介绍如何通过 AWS CloudFormation 实现 GitHub Actions 与 Amazon ECR 的安全集成,利用 OIDC(OpenID Connect)技术消除长期凭证风险,构建符合企业级安全标准的 CI/CD…

JMeter常用断言方式

简介 接口断言是接口测试中用于验证响应结果是否符合预期的关键机制&#xff0c;根据业务需求编写脚本添加断言&#xff0c;可验证接口的正确性。以下内容仅记录常用的断言方式&#xff0c;多个接口都有断言时可以使用事务控制器来隔离不同的断言。 断言方式 1、响应断言 1.…

web服务器搭建nginx

1 配置主机ip 1.1获取主机ip ip a rootpc:/home/ruxin# ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft foreve…

ubuntu ollama 遇到的若干问题

服务器原先有ollama&#xff0c;想要重装&#xff0c;遇到一系列问题 安装下载连接&#xff1a;https://github.com/ollama/ollama/blob/main/docs/linux.md模型下载链接&#xff1a;https://ollama.com/library/deepseek-r1:1.5b 一、安装新的ollama 在root用户下操作 1.卸…