本文最后更新于 2024-04-23,文章内容可能已经过时。

数组监听

需求:主要功能是从两个数组中提取相同的值,赋值到另一个数组里面,另一个函数继承这个类,并且实现监听这个这个数组的变化

为了实现您的需求,我们可以创建一个名为 ArrayIntersectionFinder 的基类,包含一个 findIntersection 方法用于找出两个数组的交集。然后,创建一个子类 ArrayIntersectionObserver 继承自 ArrayIntersectionFinder,并在子类中添加一个 observeIntersection 方法,用于监听交集数组的变化。这里假设您希望监听的是原始数组(array1array2)的变化,并在变化发生时重新计算交集。

这里我们借助 Proxy 对象来代理原始数组,以便捕获其增删改操作。当检测到数组发生变化时,自动调用 updateIntersection 方法更新交集。

class ArrayIntersectionFinder {
    /**
     * Finds the intersection of two arrays and returns the common elements in a new array.
     * @param {Array} array1 The first array.
     * @param {Array} array2 The second array.
     * @returns {Array} A new array containing the common elements found in both input arrays.
     */
    findIntersection(array1, array2) {
        const set1 = new Set(array1);
        const intersection = [];

        for (const element of array2) {
            if (set1.has(element)) {
                intersection.push(element);
            }
        }

        return intersection;
    }
}

class ArrayIntersectionObserver extends ArrayIntersectionFinder {
    constructor(array1, array2) {
        super();

        this.array1 = this._createObservableArray(array1);
        this.array2 = this._createObservableArray(array2);
        this.intersection = this.findIntersection(this.array1, this.array2);

        this._proxyHandler = {
            set(target, prop, value) {
                Reflect.set(target, prop, value);
                this.updateIntersection();
                return true;
            },
            deleteProperty(target, prop) {
                const deleted = Reflect.deleteProperty(target, prop);
                if (deleted) {
                    this.updateIntersection();
                }
                return deleted;
            },
            preventExtensions(target) {
                throw new Error('Extending the observed array is not allowed');
            }
        };
    }

    _createObservableArray(array) {
        return new Proxy(array, this._proxyHandler);
    }

    /**
     * Updates the intersection array based on the current state of the observed arrays.
     */
    updateIntersection() {
        this.intersection = this.findIntersection(this.array1, this.array2);
        // Optionally, trigger an event or call a callback here to notify listeners about the updated intersection
    }

    /**
     * Returns the current intersection array.
     * @returns {Array} The intersection of the observed arrays.
     */
    getIntersection() {
        return this.intersection;
    }
}

// Example usage:
const observer = new ArrayIntersectionObserver([1, 2, 3, 4, 5], [4, 5, 6, 7, 8]);
console.log(observer.getIntersection()); // Output: [4, 5]

// Modify one of the observed arrays
observer.array1.push(9);
console.log(observer.getIntersection()); // Output: [4, 5]

koa 封装一个连接数据库的类

需求是,可以判断自动判断是MySQL还是MongoDB,

const Koa = require('koa');
const mysql = require('mysql2/promise');
const MongoClient = require('mongodb').MongoClient;

class DatabaseConnectionManager {
  constructor(configs) {
    this.configs = configs;
    this.connections = {};
  }

  async connect() {
    for (const config of this.configs) {
      const { type, ...connectionConfig } = config;
      let connection;

      switch (type.toLowerCase()) {
        case 'mysql':
          connection = await mysql.createConnection(connectionConfig);
          break;
        case 'mongodb':
          connection = await MongoClient.connect(connectionConfig.url, connectionConfig.options);
          break;
        default:
          throw new Error(`Unsupported database type: ${type}`);
      }

      this.connections[type] = connection;
    }
  }

  getConnection(type) {
    if (!this.connections[type]) {
      throw new Error(`No active connection for type ${type}`);
    }
    return this.connections[type];
  }

  async disconnect() {
    const promises = Object.values(this.connections).map(async (connection) => {
      switch (typeof connection.close) {
        case 'function':
          await connection.close();
          break;
        case 'object':
          if (typeof connection.close === 'function') {
            await connection.close();
          } else {
            await connection.client.close();
          }
          break;
        default:
          throw new Error('Invalid connection object');
      }
    });

    await Promise.all(promises);
    this.connections = {};
  }
}

module.exports = DatabaseConnectionManager;

Koa应用中使用:

const Koa = require('koa');
const DatabaseConnectionManager = require('./DatabaseConnectionManager');

const app = new Koa();

const dbConfigs = [
  {
    type: 'mysql',
    host: 'localhost',
    user: 'your_user',
    password: 'your_password',
    database: 'your_database',
  },
  {
    type: 'mongodb',
    url: 'mongodb://localhost:27017',
    options: { useNewUrlParser: true, useUnifiedTopology: true },
  },
];

const dbManager = new DatabaseConnectionManager(dbConfigs);

app.listen(3000, async () => {
  try {
    await dbManager.connect();
    console.log('Database connections established');
  } catch (error) {
    console.error('Error connecting to databases:', error);
    process.exit(1);
  }
});

// 在Koa中间件或路由处理器中使用数据库连接
app.use(async (ctx, next) => {
  const mysqlConn = dbManager.getConnection('mysql');
  const mongoConn = dbManager.getConnection('mongodb');

  // 使用数据库连接...

  await next();
});

// 应用关闭时断开数据库连接
process.on('SIGINT', async () => {
  await dbManager.disconnect();
  console.log('Database connections closed');
  process.exit(0);
});

后端老狗不讲武德

遇到一个很没有职业道德的后端,一个接口返回了一个新世界,要做优化。

需求是将一个json中的isisArry为1的数组,放到一个新的对象中。本来就简单的处理下,后来发现这数据,不是一般大。

https://developer.mozilla.org/zh-CN/docs/Web/API/ReadableStream

	import { ReadableStream, TransformStream } from 'web-streams-polyfill/ponyfill'; //做兼容

    class StreamArrayExtractor {
        /**
         * 构造函数,接收一个生成器函数或可迭代对象作为参数
         * @param {GeneratorFunction|AsyncIterable} dataSource - 用于生成过万条数据的生成器函数或可迭代对象
         */
        constructor(dataSource) {
            this.dataSource = dataSource;
            this.extractedArrays = {};
        }

        /**
         * 使用流式API提取isArry为1的数组到新对象中
         * @returns {Promise<Object>} - 返回一个Promise,解析后得到提取后的数组对象
         */
        async extractArrays() {
            const reader = this.createReader();
            const transformer = this.createTransformer();
            const writer = this.createWriter();

            return new Promise((resolve, reject) => {
                reader.read()
                    .then(() => {
                        reader.pipeThrough(transformer).pipeTo(writer);
                        writer.closed
                            .then(resolve)
                            .catch(reject);
                    })
                    .catch(reject);
            });
        }

        createReader() {
            return new ReadableStream({
                start(controller) {
                    const iterator = this.dataSource[Symbol.asyncIterator]();
                    (async function read() {
                        let result;
                        try {
                            result = await iterator.next();
                        } catch (err) {
                            controller.error(err);
                            return;
                        }

                        if (result.done) {
                            controller.close();
                            return;
                        }

                        controller.enqueue(result.value);
                        read();
                    })();
                },
            });
        }

        createTransformer() {
            return new TransformStream({
                transform(chunk, controller) {
                    if (chunk.isArry === 1 && Array.isArray(chunk.arrayContent)) {
                        const key = chunk.keyForExtractedArrays; // 替换为实际用于作为新对象键值的属性名

                        if (!this.extractedArrays[key]) {
                            this.extractedArrays[key] = [];
                        }

                        this.extractedArrays[key].push(...chunk.arrayContent);
                    }
                },
            });
        }

        createWriter() {
            return new WritableStream({
                write() { },
                close() {
                    return this.extractedArrays;
                },
            });
        }
    }

    // 使用示例:
    const dataSource = /* 一个生成器函数或可迭代对象 */;
    const extractor = new StreamArrayExtractor(dataSource);
    const extractedArraysPromise = extractor.extractArrays();
    extractedArraysPromise.then(extractedArrays => console.log(extractedArrays));