Promise的理解
/* 对于原生的promise的使用:
promise对象在创建时传入业务的回调函数;
该回调函数需要传递两个参数,resovle与reject用于针对业务的完成情况改变promise状态
promise包含三种状态:pending等待任务完成,fulfilled:任务完成,rejected:任务失败
当一个promise的状态不再是pending状态那么peromise的状态将不再发生改变
promise中的then函数会根据当前promise的执行结果或者状态选择调用回调函数并,返回一个新的promise*/
/* const promise = new Promise((resolve,reject)=>{
console.log(1111);
resolve(1);
})
promise.then((res)=>{
return res;
}).then((res)=>{
console.log(res)
}) */
/* 手撕开始 */
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
class MyPromise{
/* 定义私有成员变量 ,并初始化*/
#states = "pending"
#result = null
#handles = []
/* 创建一个微服务,使得异步执行完毕后尽快执行相关的回调代码 */
nextTick(fn){
// 是node环境
if (process && process.nextTick) {
process.nextTick(fn)
} else {
// 不是node环境,setTimeout适用于其他环境,比如浏览器
setTimeout(fn, 0)
}
}
/* 这里为什么要单独使用run函数执行这些回调函数,首先在执行then方法的时候可能出现的情况是
当前promise的状态还是pending状态,这时候显然不能去执行then的回调函数,我们需要在当前peomise
状态改变那一刻去执行回调函数,这里利用一个handles映射这些回调函数,再在一个单独的函数中去
调用这些函数。这个handles是一个数组是因为用户可能多次去调用then函数*/
#changStates(states,res)
{
if(this.#states === PENDING){
this.#result = res;
this.#states = states;
}
this.#run();
}
#runOne(states,callBack,resolve,reject){
this.nextTick(()=>{
if(this.#states!==states)return;
if(typeof callBack ==="function"){
try{
const data = callBack(this.#result);
resolve(data);
} catch (err) {
reject(err)
}
}else{
if(this.#states ===FULFILLED){
resolve(this.#result)
}else{
reject(this.#result)
}
return
}
})
}
/*哪些情况下使用 resolve, reject:
首先传递的不是函数————穿透
第二中传入执行的回调函数运行时抛出异常,这里reject返回结果
回调函数的返回结果是一个promise*/
#run(){
if(this.#states === PENDING)return;
while(this.#handles.length){
const {fnRes, fnRej, resolve, reject} = this.#handles.shift();
if(this.#states === FULFILLED){
this.#runOne(this.#states,fnRes,resolve,reject);
}else{
this.#runOne(this.#states,fnRej,resolve,reject);
}
}
}
resolve(res){
this.#changStates(FULFILLED,res);
}
reject(err){
this.#changStates(REJECTED,err);
}
then(fnRes,fnRej){
return new Promise((resolve,reject)=>{
this.#handles.push(
{
fnRes,
fnRej,
resolve,
reject
}
)
this.#run();
})
}
/* 在构造函数中定义resolve与reject函数,可以在构造函数外部定义
但是需要注意的是在外部定义,当函数以独立函数形式调用时, this
默认指向全局对象(在浏览器环境下是 window 对象,Node.js 环境下
是 global 对象。)如果我们要将该函数以作为对象的方法调用需要将
this的指向绑定为当前对象的this指向 例如:this.resolve(this),实
际还是定义了一个新的成员方法,这里也可以直接在构造函数中定义*/
constructor(excutor){
excutor(this.resolve.bind(this),this.reject.bind(this));
};
}
const my =new MyPromise((resolve,reject)=>{
setTimeout(()=>{
reject(2);
},1000)
});
const pro = my.then(111,111)
pro.then(111,(res)=>{
console.log(res)
})
在计算机上实现两个串口通信
创建了两个虚拟串口
#include<windows.h>
#include<stdio.h>
#define VIR_COM_S "COM1" //指定串口
#define VIR_COM_R "COM2" //指定串口
#define VIR_BAUD 9600 //设置波特率
#define PRIOTY ODDPARITY//校验方式
#define BUFFER_SIZE 1024
HANDLE open_port(char *port) //打开串口
{
HANDLE hcom = CreateFileA(port,GENERIC_READ | GENERIC_WRITE,0,NULL,
OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if(hcom == INVALID_HANDLE_VALUE){
printf("串口打开失败\n");
return INVALID_HANDLE_VALUE;
}else{
return hcom;
}
}
BOOL SetUpPort(HANDLE hcom){
DCB dcb;//串行通信的控制块
dcb.DCBlength = sizeof(DCB);
if(!GetCommState(hcom,&dcb)){
printf("获取串口状态失败\n");
return FALSE;
}
dcb.BaudRate = VIR_BAUD;
dcb.ByteSize = 8;
dcb.StopBits = ONESTOPBIT;//设置停止位的长
dcb.Parity = PRIOTY;//设置校验
if(!SetCommState(hcom,&dcb)){//设置串口状态
printf("设置串口状态失败\n");
return FALSE;
};
// 设置超时参数
COMMTIMEOUTS timeouts;
timeouts.ReadIntervalTimeout = MAXDWORD;
timeouts.ReadTotalTimeoutMultiplier = 0;
timeouts.ReadTotalTimeoutConstant = 0;
timeouts.WriteTotalTimeoutMultiplier = 0;
timeouts.WriteTotalTimeoutConstant = 0;
if (!SetCommTimeouts(hcom, &timeouts)) {
printf("Error setting timeouts: %d\n", GetLastError());
CloseHandle(hcom);
return FALSE;
}
return TRUE;
}
// 发送数据到串口
BOOL WriteToSerialPort(HANDLE hSerial, const char *data) {
DWORD bytesWritten;
if (!WriteFile(hSerial, data, strlen(data), &bytesWritten, NULL)) {
printf("Error writing to serial port: %d\n", GetLastError());
return FALSE;
}
return TRUE;
}
// 从串口读取数据
BOOL ReadFromSerialPort(HANDLE hSerial, char *buffer, DWORD size) {
DWORD bytesRead;
if (!ReadFile(hSerial, buffer, size, &bytesRead, NULL)) {
printf("Error reading from serial port: %d\n", GetLastError());
return FALSE;
}
buffer[bytesRead] = '\0'; // 添加结束符以形成字符串
return TRUE;
}
int main() {
HANDLE hSerial_s = open_port(VIR_COM_S);
HANDLE hSerial_r = open_port(VIR_COM_R);
if (hSerial_s != INVALID_HANDLE_VALUE) {
if (!SetUpPort(hSerial_s)) {
CloseHandle(hSerial_s);
}
}
if (hSerial_r != INVALID_HANDLE_VALUE) {
if (!SetUpPort(hSerial_r)) {
CloseHandle(hSerial_r);
}
}
char sendData[] = "Hello, World!";
WriteToSerialPort(hSerial_s, sendData);
char receiveBuffer[BUFFER_SIZE];
ReadFromSerialPort(hSerial_r, receiveBuffer, BUFFER_SIZE);
printf("Received: %s\n", receiveBuffer);
CloseHandle(hSerial_s);
CloseHandle(hSerial_r);
return 0;
}
IIC通信伪实现:
#include<stdio.h>
#include<stdlib.h>
int transfer(int R1){
printf("%d\n",R1);
}
typedef struct ADR_R_W{
char R_W:1;
char address:7;
}ADR;//确定接收地址编号以及发送形式。
typedef char DATA;
int main(){
int R1;//SDA寄存器内容,0、1、2、4分别代表低电平、低高跳变、高低跳变、高电平。
int R2;//SCL寄存器内容,0、1、2、4分别代表低电平、低高跳变、高低跳变、高电平。
while(1){
scanf("%d%d",&R1,&R2);
//SCL信号为高电平,而SDA信号变为低电平开始传输数据;
if(R1 == 2 && R2 == 4){
scanf("%d\n",&R2);
if(R2 == 2)//scl由高到低开始传输数据;
{
ADR* st = (ADR*)malloc(sizeof(ADR));
scanf("%c",st);//确定从站地址;
char* add = (char*)st;
int len = 8;
while(len--){
printf("时钟周期%d---",8-len);
R1 = (*add)%2;
*add = (*add)/2;
transfer(R1);
}
//
if(st->R_W == 1){
while(1){
//读取模式;
printf("收到ACK和数据");
scanf("%d%d\n",&R1,&R2);
if(R1 ==1 && R2 == 4){
free(st);
printf("结束通信");
break;
}
R1 = 4;
printf("回复ACK");
transfer(R1);
}
}
else{
//写模式;
//传输data;
printf("收到回复数据");
DATA data;//写入数据
while(1){
scanf("%d%d\n",&R1,&R2);//判断是否结束
if(R1 ==1 && R2 == 4){
free(st);
printf("结束通信\n");
break;
}
scanf("%c",&data);
int len = 8;
while(len--){
printf("时钟周期%d---",8-len);
R1 = (data)%2;
data = (data)/2;
transfer(R1);
}
}
}
}
}
}
}