我的第一个npm包

4 篇文章 0 订阅

前言:最近对前端的兴趣越来越大,于是决定把之前量化回测的代码从java改为用ts重写,数据api使用python的tushare包提供。我在调用api的时候想要写一个函数缓存,因为有的数据量特别大,每次调用都比较耗时,在java里面我可以使用HashMap来实现,在js里面呢?我在es6里面找到了Map这个数据结构,但是一番尝试后我发现Map只能对基本的数据类型使用值作为key的存储,如果值是对象的话,key存储的是这个对象的引用。于是我决定自己实现一个简单的HashMap,目前的实现很简单,如果键是基本类型的话直接存储,如果是对象类型的话,则使用JSON.stringify将对象转化为字符串(这里见笑了,后面想办法换成比较高效的解决方法);代码测试通过后,就想把这个包发布到npm上,之前写过java包,但是发布到maven上异常的麻烦,没想到发布到npm上这么简单:
1.在npm上注册账号
2.在项目路径下npm add user
3.根据提示验证邮箱
4.npm publish
5.done.
下面介绍下我实现的代码(见笑了):

type basic = number | string

export class HashMap<K extends basic | object, V> implements Map<K, V>{

    private map: Map<basic, V> = new Map();
    // store key and hashcode
    private keyMap: Map<basic, K> = new Map();

    private readonly hashCode: (object: basic | object) => basic = object => {
        if (typeof object === "number" || typeof object === "string") {
            return object;
        }
        // todo need to develop better function for making the key to string
        return JSON.stringify(object);
    }

    constructor(config?: {hashCode: (object: basic | object) => basic}) {
        if (config !== undefined && config.hashCode && typeof config.hashCode === "function") {
            this.hashCode = config.hashCode;
        }
        this.size = this.map.size;
    }

    [Symbol.iterator](): IterableIterator<[K, V]> {
        return this.entries();
    }

    entries (): IterableIterator<[K, V]> {
        const keyIterator = this.keys();
        const valueIterator = this.values();
        return new class implements IterableIterator<[K, V]> {
            next(): IteratorResult<[K, V], any> {
                return {
                    done: true,
                    value: [keyIterator.next(), valueIterator.next()]
                };
            }
            [Symbol.iterator](): IterableIterator<[K, V]> {
                return this;
            }
        }
    }
    keys(): IterableIterator<K> {
        return this.keyMap.values();
    }
    values(): IterableIterator<V> {
        return this.map.values();
    }
    [Symbol.toStringTag]: string;

    size: number;

    clear(): void {
        this.map.clear();
        this.size = this.map.size;
    }

    delete(key: K): boolean {
        const hashCode = this.hashCode(key);
        this.keyMap.delete(hashCode);
        const deleteFlag = this.map.delete(this.hashCode(key));
        this.size = this.map.size;
        return deleteFlag;
    }

    forEach(callbackfn: (value: V, key: K, map: Map<K, V>) => void, thisArg?: any): void {
        this.map.forEach((value1, key1, map1) => {
            // get key
            const originalKey = this.keyMap.get(key1);
            if (typeof originalKey === undefined) {
                throw new Error(`can not find key ${key1} in HashMap's map`);
            }
            callbackfn(value1, originalKey!, this as unknown as Map<K, V>);
        })
    }

    get(key: K): V | undefined{
        return this.map.get(this.hashCode(key))
    }

    has(key: K): boolean {
        const hashCode = this.hashCode(key);
        return this.keyMap.has(hashCode);
    }

    set(key: K, value: V): this {
        const hashCode = this.hashCode(key);
        this.keyMap.set(hashCode, key);
        this.map.set(hashCode, value);
        this.size = this.map.size;
        return this;
    }

}



测试

import {HashMap} from "./hashmap";

test('new HashMap', () => {
    const map = new HashMap();
    expect(map.size).toBe(0);
})

test('set & get', () => {
    const map = new HashMap();
    map.set({a: 1, b: 2}, 3);
    const v = map.get({a: 1, b: 2});
    expect(v).toBe(3);
})

test('Symbol.iterator', () => {
    const map = new HashMap();
    map.set(1, 2);
    for (let [k, v] of map) {
        expect(k).toBe(1);
        expect(v).toBe(2);
    }
})

test('entries', () => {
    const map = new HashMap();
    map.set(1, 2);
    for (let [k, v] of map.entries()) {
        expect(k).toBe(1);
        expect(v).toBe(2);
    }
})

test('keys & values', () => {
    const map = new HashMap();
    map.set(1, 2);
    for (let k of map.keys()) {
        expect(k).toBe(1);
    }
    for (let v of map.values()) {
        expect(v).toBe(2);
    }
})

test('size', () => {
    const map = new HashMap();
    map.set(1, 2);
    expect(map.size).toBe(1);
})

test('clear', () => {
    const map = new HashMap();
    map.set(1, 2);
    expect(map.size).toBe(1);
    map.clear();
    expect(map.size).toBe(0);
})

test('delete', () => {
    const map = new HashMap();
    map.set(1, 2);
    expect(map.size).toBe(1);
    map.delete(1);
    expect(map.size).toBe(0);
    map.set({a: 1, b: 2}, 3);
    expect(map.size).toBe(1);
    map.delete({a: 1, b: 2});
    expect(map.size).toBe(0);
})

test('forEach', () => {
    const map = new HashMap();
    map.set(1, 2);
    map.set(2, 3);
    map.forEach(((value, key, map) => {
        expect(value === 2 || value === 3).toBe(true);
        expect(key === 1 || key === 2).toBe(true);
    }))
})

test('has', () => {
    const map = new HashMap();
    map.set(1, 2);
    map.set({a: 1, b: 2}, 3);
    expect(map.has(1)).toBe(true);
    expect(map.has({a: 1, b: 2})).toBe(true);
})

github地址:
https://github.com/Mng12345/mng-easy-util
npm:
npm i mng-easy-util

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值