首页 > 其他分享 >一次泛型丢失问题记录

一次泛型丢失问题记录

时间:2024-03-20 15:11:38浏览次数:20  
标签:const 记录 .# inQueue Promise someThing 泛型 丢失

问题来源

在实现一步一步实现一个基于信号量与队列的简单并发控制类 - Cat_Catcher - 博客园 (cnblogs.com)这篇文章中的并发控制类的时候,遇到了一个泛型丢失的问题。问题的核心在于入队的时候,对象成员的类型是:

type QueueMember<T> = {
  toRequest: () => Promise<T>;
  resolve: (value: T | PromiseLike<T>) => void;
  reject: (reason?: any) => void;
};

<T>的类型是请求方法返回的Promise的泛型,例如:async function requestProfile(uid: string): Promise<string>中的string

在入队的时候可以看到类型是可以追溯的
image

但是出队的时候泛型“丢失”了,或者说我不知道应该如何正确传递此泛型
image

最小化问题

上面所述问题本质上是下面这个问题:

const queue: any[] = [];

function inQueue<T>(someThing: T) {
  queue.push(someThing);
}
function outQueue() {
  const someThing = queue.pop();
}

inQueue("hi");
inQueue(123);

问题在于入队的时候,可以追踪到泛型T指的是inQueue调用时的类型,也就是例子中的stringnumber
image

但是在出队的时候,泛型T丢失了
image

解决方法

通过引入一个高阶函数helper,显式的指明泛型,使得ts的类型系统可以追踪到即可。

type Helper = <R>(helperCb: <T>(someThing: T) => R) => R;
const helper =
  <T>(someThing: T): Helper =>
  (helperCb) =>
    helperCb(someThing);

const queue: Helper[] = [];

function inQueue<T>(someThing: T) {
  queue.push(helper(someThing));
}
function outQueue() {
  const getSomeThing = queue.pop()!;
  getSomeThing((someThing) => {
    someThing;
  });
}

inQueue("hi");
inQueue(123);

实现泛型追踪
image

原问题解决之后的完整代码

async function requestProfile(uid: string): Promise<string> {
  // 模拟用户头像请求
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(`UserProfile-${uid}`);
    }, 1000);
  });
}

async function loadUserProfiles() {
  const start = new Date().getTime();
  const uids: string[] = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"];
  const queue = new AsyncLimitQueue(5);
  const profiles = await Promise.all(uids.map((id) => queue.inQueue(() => requestProfile(id))));
  console.log(new Date().getTime() - start > 2000 && new Date().getTime() - start < 3000, profiles);
}

loadUserProfiles();

type QueueMember<T> = {
  toRequest: () => Promise<T>;
  resolve: (value: T | PromiseLike<T>) => void;
  reject: (reason?: any) => void;
};
// 解决泛型丢失问题
type SomeQueueMember = <R>(cb: <T>(qm: QueueMember<T>) => R) => R;
const someQueueMember =
  <T>(qm: QueueMember<T>): SomeQueueMember =>
  (cb) =>
    cb(qm);

class AsyncLimitQueue {
  #limit = 7;
  #waitingQueue: Array<SomeQueueMember> = [];

  constructor(limit?: number) {
    this.#limit = limit ?? this.#limit;
  }

  #execWaitingQueue() {
    if (this.#limit === 0 || this.#waitingQueue.length === 0) return;

    const sqm = this.#waitingQueue.shift()!;
    sqm(({ toRequest, resolve, reject }) => {
      this.#limit--; // 减少信号量
      toRequest()
        .then(resolve)
        .catch(reject)
        .finally(() => {
          this.#limit++; // 增加信号量
          this.#execWaitingQueue(); // 尝试执行等待队列中的请求
        });
    });
  }
  inQueue<T>(toRequest: () => Promise<T>): Promise<T> {
    return new Promise<T>((resolve, reject) => {
      // 所有请求先入队
      this.#waitingQueue.push(
        someQueueMember({
          toRequest,
          resolve,
          reject,
        })
      );
      // 尝试执行等待队列
      this.#execWaitingQueue();
    });
  }
}

标签:const,记录,.#,inQueue,Promise,someThing,泛型,丢失
From: https://www.cnblogs.com/CatCatcher/p/18085268

相关文章

  • STM32发送串口数据丢失字节的解决办法
    发送数据函数voidUsart3_Send_Array(u8*buf,u8len){u8t;GPIO_WriteBit(GPIOB,RS485AB_EN_PIN,1);for(t=0;t<len;t++) //循环发送数据{while(USART_GetFlagStatus(USART3,USART_FLAG_TXE)==RESET);USART_SendData(USART3,......
  • fastjson记录
    参考指南fastjson:我一路向北,离开有你的季节|素十八(su18.org)Java反序列化漏洞始末(3)—fastjson-浅蓝'sblog(b1ue.cn)梅子酒の笔记本(meizjm3i.github.io)fastjson基础早期版本的fastjson的框架图fastjson功能要点:fastjson在创建一个类实例时会通过反射......
  • 庆军之菜鸟记录-定期检查并删除数据
    不得不说,跟大佬们的差距是亿点点啊。1privateasyncTaskExpiryScanLoop()2{3varcancelToken=_scanExpiryCancellationToken!.Token;4while(cancelToken.IsCancellationRequested==false)5{6try7{8await......
  • 找到丢失的数,异或运算解题
    //存在一个数组A包含n-1个数,这些数为1到n之间的整数,请找到丢失的数?//这里采用异或运算(都为二进制运算)://1.相同数异或为0//2.不同值异或为1//3.0^0=0//4.0^x=x(x不为0)//......
  • C++ 泛型编程
    1.函数模板假设我们设计一个交换两个整型变量的值的函数,代码如下://交换两个整型变量的值的Swap函数:voidSwap(int&x,int&y){inttmp=x;x=y;y=tmp;}如果是浮点类型的变量的值交换,则替换int类型为double即可,代码如下://交换两个double型变量......
  • C# 中使对象序列化/反序列化 Json 支持使用派生类型以及泛型的方式
    C#中使对象序列化/反序列化Json支持使用派生类型以及泛型方式废话#前言#为啥想写这个博客最近自己写的框架有用到这个类似工作流,支持节点编码自定义,动态运行自定义.尽量减少动态解析这就需要确定类型.有什么好的奇思妙想可以一起来讨论噢(现在还是毛坯,测......
  • ssts-hospital-web-master项目实战记录五十:项目迁移-页面模块实现(主框架-文件结构)
    记录时间:2024-03-20文件结构 翻译搜索复制......
  • ssts-hospital-web-master项目实战记录四十九:项目迁移-业务模块实现(静态资源-文件结构
    记录时间:2024-03-20文件结构 翻译搜索复制......
  • Unity类银河恶魔城学习记录11-2 p104 Inventoty源代码
     此章节相对较难理解,有时间单独出一章讲一下Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释,可供学习Alex教程的人参考此代码仅为较上一P有所改变的代码【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibiliInventoryItem.csusingSystem;usingSy......
  • electron安装成功记录
    1.登录官网查看当前最新版本对应的node,注意这里不要看php那个汉化的,他那个是老版本的,node对不上 2.nvm安装一个新的node 3.使用cnpm安装(npm安装还是报错了,记得删node_moudules) ......