name: 代码片段管理器 description: 使用标签、分类和智能搜索功能保存、组织、搜索和检索代码片段…
代码片段管理器技能
使用标签、分类和智能搜索功能保存、组织、搜索和检索代码片段。
使用说明
您是一个代码片段管理专家。调用时:
-
保存代码片段:
- 提取可重用的代码模式
- 添加元数据(语言、标签、描述)
- 按类别和用例组织
- 对片段变体进行版本控制
-
搜索和检索:
- 按语言、标签或关键词搜索
- 查找相似模式
- 根据上下文建议相关片段
- 按框架或库过滤
-
片段组织:
- 逻辑分类片段
- 使用相关关键词标记
- 分组相关片段
- 创建片段集合
-
片段增强:
- 添加使用示例
- 记录参数和选项
- 包括边缘情况
- 提供替代实现
片段类别
- 语言基础:常见模式、惯用语、语法助手
- 数据结构:数组、对象、映射、集合操作
- 算法:排序、搜索、递归、动态规划
- API模式:REST客户端、错误处理、身份验证
- 数据库:查询、迁移、ORM模式
- 测试:测试设置、模拟、断言
- React/Vue/Angular:组件模式、钩子、指令
- Node.js:Express中间件、流、文件操作
- Python:装饰器、上下文管理器、生成器
- DevOps:Docker、CI/CD、部署脚本
- 实用工具:日期/时间、字符串操作、验证
使用示例
@snippet-manager 保存API错误处理程序
@snippet-manager --search "react hooks"
@snippet-manager --category 测试
@snippet-manager --language python
@snippet-manager --tag async
@snippet-manager --collection "身份验证模式"
片段格式
基本片段结构
# 片段:异步错误处理程序包装器
**语言**:JavaScript/TypeScript
**类别**:错误处理
**标签**:async, error-handling, middleware, express
**框架**:Express.js
**用例**:包装异步路由处理程序以捕获错误
## 代码
```javascript
const asyncHandler = (fn) => (req, res, next) => {
Promise.resolve(fn(req, res, next)).catch(next);
};
// 使用
app.get('/users/:id', asyncHandler(async (req, res) => {
const user = await User.findById(req.params.id);
res.json(user);
}));
参数
fn:要包装的异步函数 (Request, Response, NextFunction) => Promise<void>
返回值
Express中间件函数,处理承诺拒绝
备注
- 消除路由处理程序中的try-catch块
- 将错误传递给Express错误处理中间件
- 适用于任何异步函数
相关片段
## JavaScript/TypeScript片段
### 防抖函数
```javascript
// 片段:防抖
// 类别:性能
// 标签:debounce, performance, optimization
function debounce(func, wait, immediate = false) {
let timeout;
return function executedFunction(...args) {
const later = () => {
timeout = null;
if (!immediate) func.apply(this, args);
};
const callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(this, args);
};
}
// 使用
const handleSearch = debounce((query) => {
fetchResults(query);
}, 300);
// 在React中
const [searchTerm, setSearchTerm] = useState('');
const debouncedSearch = useMemo(
() => debounce((term) => {
// 执行搜索
console.log('搜索:', term);
}, 500),
[]
);
useEffect(() => {
debouncedSearch(searchTerm);
}, [searchTerm, debouncedSearch]);
深克隆对象
// 片段:深克隆
// 类别:数据结构
// 标签:clone, deep-copy, objects
// 方法1:JSON(仅简单对象)
const deepClone = (obj) => JSON.parse(JSON.stringify(obj));
// 方法2:结构化克隆(现代浏览器/Node.js)
const deepClone2 = (obj) => structuredClone(obj);
// 方法3:自定义递归(处理复杂类型)
function deepClone3(obj, hash = new WeakMap()) {
if (Object(obj) !== obj) return obj; // 基本类型
if (hash.has(obj)) return hash.get(obj); // 循环引用
const result = Array.isArray(obj)
? []
: obj.constructor
? new obj.constructor()
: Object.create(null);
hash.set(obj, result);
return Object.assign(
result,
...Object.keys(obj).map(key => ({
[key]: deepClone3(obj[key], hash)
}))
);
}
// 使用
const original = { a: 1, b: { c: 2 }, d: [3, 4] };
const cloned = deepClone(original);
cloned.b.c = 999; // original.b.c仍为2
指数退避重试
// 片段:指数退避重试
// 类别:错误处理
// 标签:retry, async, error-handling, resilience
async function retryWithBackoff<T>(
fn: () => Promise<T>,
options: {
maxRetries?: number;
initialDelay?: number;
maxDelay?: number;
factor?: number;
} = {}
): Promise<T> {
const {
maxRetries = 3,
initialDelay = 1000,
maxDelay = 30000,
factor = 2,
} = options;
let lastError: Error;
let delay = initialDelay;
for (let attempt = 0; attempt <= maxRetries; attempt++) {
try {
return await fn();
} catch (error) {
lastError = error as Error;
if (attempt === maxRetries) {
throw new Error(
`在${maxRetries}次重试后失败:${lastError.message}`
);
}
console.log(`第${attempt + 1}次尝试失败,${delay}毫秒后重试...`);
await new Promise(resolve => setTimeout(resolve, delay));
delay = Math.min(delay * factor, maxDelay);
}
}
throw lastError!;
}
// 使用
const data = await retryWithBackoff(
() => fetch('https://api.example.com/data').then(r => r.json()),
{ maxRetries: 5, initialDelay: 500 }
);
带过期的本地存储
// 片段:带过期的本地存储
// 类别:浏览器API
// 标签:localstorage, cache, expiry
const storage = {
set(key, value, expiryMs = null) {
const item = {
value,
expiry: expiryMs ? Date.now() + expiryMs : null,
};
localStorage.setItem(key, JSON.stringify(item));
},
get(key) {
const itemStr = localStorage.getItem(key);
if (!itemStr) return null;
const item = JSON.parse(itemStr);
if (item.expiry && Date.now() > item.expiry) {
localStorage.removeItem(key);
return null;
}
return item.value;
},
remove(key) {
localStorage.removeItem(key);
},
clear() {
localStorage.clear();
},
};
// 使用
storage.set('user', { id: 1, name: 'John' }, 3600000); // 1小时
const user = storage.get('user');
React片段
自定义useDebounce钩子
// 片段:useDebounce钩子
// 类别:React钩子
// 标签:react, hooks, debounce, performance
import { useEffect, useState } from 'react';
function useDebounce<T>(value: T, delay: number): T {
const [debouncedValue, setDebouncedValue] = useState<T>(value);
useEffect(() => {
const handler = setTimeout(() => {
setDebouncedValue(value);
}, delay);
return () => {
clearTimeout(handler);
};
}, [value, delay]);
return debouncedValue;
}
// 使用
function SearchComponent() {
const [searchTerm, setSearchTerm] = useState('');
const debouncedSearchTerm = useDebounce(searchTerm, 500);
useEffect(() => {
if (debouncedSearchTerm) {
// 执行搜索
fetchResults(debouncedSearchTerm);
}
}, [debouncedSearchTerm]);
return (
<input
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
/>
);
}
自定义useAsync钩子
// 片段:useAsync钩子
// 类别:React钩子
// 标签:react, hooks, async, data-fetching
import { useEffect, useState, useCallback } from 'react';
type Status = 'idle' | 'loading' | 'success' | 'error';
interface AsyncState<T> {
status: Status;
data: T | null;
error: Error | null;
}
function useAsync<T>(
asyncFunction: () => Promise<T>,
immediate = true
) {
const [state, setState] = useState<AsyncState<T>>({
status: 'idle',
data: null,
error: null,
});
const execute = useCallback(async () => {
setState({ status: 'loading', data: null, error: null });
try {
const data = await asyncFunction();
setState({ status: 'success', data, error: null });
return data;
} catch (error) {
setState({ status: 'error', data: null, error: error as Error });
throw error;
}
}, [asyncFunction]);
useEffect(() => {
if (immediate) {
execute();
}
}, [execute, immediate]);
return { ...state, execute };
}
// 使用
function UserProfile({ userId }) {
const { status, data, error } = useAsync(
() => fetch(`/api/users/${userId}`).then(r => r.json()),
true
);
if (status === 'loading') return <div>加载中...</div>;
if (status === 'error') return <div>错误:{error.message}</div>;
if (status === 'success') return <div>用户:{data.name}</div>;
return null;
}
自定义useLocalStorage钩子
// 片段:useLocalStorage钩子
// 类别:React钩子
// 标签:react, hooks, localstorage, persistence
import { useState, useEffect } from 'react';
function useLocalStorage<T>(
key: string,
initialValue: T
): [T, (value: T | ((val: T) => T)) => void] {
// 从本地存储读取,然后解析存储的JSON或返回初始值
const readValue = (): T => {
if (typeof window === 'undefined') {
return initialValue;
}
try {
const item = window.localStorage.getItem(key);
return item ? JSON.parse(item) : initialValue;
} catch (error) {
console.warn(`读取本地存储键"${key}"时出错:`, error);
return initialValue;
}
};
const [storedValue, setStoredValue] = useState<T>(readValue);
const setValue = (value: T | ((val: T) => T)) => {
try {
const valueToStore =
value instanceof Function ? value(storedValue) : value;
setStoredValue(valueToStore);
if (typeof window !== 'undefined') {
window.localStorage.setItem(key, JSON.stringify(valueToStore));
}
} catch (error) {
console.warn(`设置本地存储键"${key}"时出错:`, error);
}
};
useEffect(() => {
setStoredValue(readValue());
}, []);
return [storedValue, setValue];
}
// 使用
function App() {
const [theme, setTheme] = useLocalStorage('theme', 'light');
return (
<button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
当前主题:{theme}
</button>
);
}
Python片段
重试装饰器
# 片段:重试装饰器
# 类别:错误处理
# 标签:python, decorator, retry, error-handling
import time
import functools
from typing import Callable, Type
def retry(
max_attempts: int = 3,
delay: float = 1.0,
backoff: float = 2.0,
exceptions: tuple[Type[Exception], ...] = (Exception,)
):
"""
指数退避重试装饰器
参数:
max_attempts:最大重试尝试次数
delay:初始重试延迟(秒)
backoff:每次重试后延迟的乘数
exceptions:要捕获的异常元组
"""
def decorator(func: Callable):
@functools.wraps(func)
def wrapper(*args, **kwargs):
current_delay = delay
last_exception = None
for attempt in range(max_attempts):
try:
return func(*args, **kwargs)
except exceptions as e:
last_exception = e
if attempt == max_attempts - 1:
raise
print(f"第{attempt + 1}次尝试失败:{e}")
print(f"{current_delay}秒后重试...")
time.sleep(current_delay)
current_delay *= backoff
raise last_exception
return wrapper
return decorator
# 使用
@retry(max_attempts=5, delay=0.5, exceptions=(ConnectionError, TimeoutError))
def fetch_data(url: str):
response = requests.get(url, timeout=10)
response.raise_for_status()
return response.json()
计时上下文管理器
# 片段:计时上下文管理器
# 类别:性能
# 标签:python, context-manager, timing, profiling
import time
from contextlib import contextmanager
from typing import Optional
@contextmanager
def timer(name: Optional[str] = None):
"""
用于计时代码执行的上下文管理器
使用:
with timer("数据库查询"):
result = db.query(...)
"""
start = time.perf_counter()
try:
yield
finally:
elapsed = time.perf_counter() - start
label = f"{name}: " if name else ""
print(f"{label}经过时间:{elapsed:.4f}秒")
# 使用
with timer("API调用"):
response = requests.get("https://api.example.com/data")
data = response.json()
# 替代:作为装饰器
def timed(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
start = time.perf_counter()
result = func(*args, **kwargs)
elapsed = time.perf_counter() - start
print(f"{func.__name__}花费了{elapsed:.4f}秒")
return result
return wrapper
@timed
def process_data(data):
# 处理数据
pass
使用LRU缓存的记忆化
# 片段:记忆化
# 类别:性能
# 标签:python, cache, memoization, optimization
from functools import lru_cache, wraps
import pickle
import hashlib
# 简单记忆化与lru_cache
@lru_cache(maxsize=128)
def fibonacci(n: int) -> int:
if n < 2:
return n
return fibonacci(n - 1) + fibonacci(n - 2)
# 自定义记忆化用于不可哈希参数
def memoize(func):
cache = {}
@wraps(func)
def wrapper(*args, **kwargs):
# 从参数创建可哈希键
key = hashlib.md5(
pickle.dumps((args, tuple(sorted(kwargs.items()))))
).hexdigest()
if key not in cache:
cache[key] = func(*args, **kwargs)
return cache[key]
wrapper.cache_clear = lambda: cache.clear()
wrapper.cache_info = lambda: f"缓存大小:{len(cache)}"
return wrapper
# 使用不可哈希类型(列表、字典)
@memoize
def expensive_computation(data: list[int]) -> int:
return sum(x ** 2 for x in data)
result = expensive_computation([1, 2, 3, 4, 5])
Node.js片段
速率限制器中间件
// 片段:速率限制器
// 类别:中间件
// 标签:nodejs, express, rate-limiting, security
class RateLimiter {
constructor(options = {}) {
this.windowMs = options.windowMs || 60000; // 1分钟
this.maxRequests = options.maxRequests || 100;
this.requests = new Map();
}
middleware() {
return (req, res, next) => {
const key = req.ip || req.connection.remoteAddress;
const now = Date.now();
if (!this.requests.has(key)) {
this.requests.set(key, []);
}
const userRequests = this.requests.get(key);
// 移除窗口外的旧请求
const validRequests = userRequests.filter(
timestamp => now - timestamp < this.windowMs
);
if (validRequests.length >= this.maxRequests) {
const oldestRequest = validRequests[0];
const resetTime = oldestRequest + this.windowMs;
const retryAfter = Math.ceil((resetTime - now) / 1000);
res.set('Retry-After', retryAfter.toString());
return res.status(429).json({
error: '请求过多',
retryAfter: retryAfter,
});
}
validRequests.push(now);
this.requests.set(key, validRequests);
res.set('X-RateLimit-Limit', this.maxRequests.toString());
res.set('X-RateLimit-Remaining',
(this.maxRequests - validRequests.length).toString()
);
next();
};
}
// 定期清理旧条目
cleanup() {
const now = Date.now();
for (const [key, timestamps] of this.requests.entries()) {
const valid = timestamps.filter(t => now - t < this.windowMs);
if (valid.length === 0) {
this.requests.delete(key);
} else {
this.requests.set(key, valid);
}
}
}
}
// 使用
const limiter = new RateLimiter({
windowMs: 15 * 60 * 1000, // 15分钟
maxRequests: 100,
});
app.use('/api', limiter.middleware());
// 每5分钟清理
setInterval(() => limiter.cleanup(), 5 * 60 * 1000);
流管道助手
// 片段:流管道
// 类别:流
// 标签:nodejs, streams, pipeline, files
const { pipeline } = require('stream');
const { promisify } = require('util');
const fs = require('fs');
const zlib = require('zlib');
const { Transform } = require('stream');
const pipelineAsync = promisify(pipeline);
// 自定义转换流
class LineCounter extends Transform {
constructor(options) {
super(options);
this.lineCount = 0;
}
_transform(chunk, encoding, callback) {
const lines = chunk.toString().split('
').length - 1;
this.lineCount += lines;
this.push(chunk);
callback();
}
}
// 使用:压缩文件并计数行数
async function compressAndCount(inputFile, outputFile) {
const counter = new LineCounter();
await pipelineAsync(
fs.createReadStream(inputFile),
counter,
zlib.createGzip(),
fs.createWriteStream(outputFile)
);
console.log(`处理了${counter.lineCount}行`);
return counter.lineCount;
}
// 使用:处理大型CSV
async function processCsv(inputFile) {
const processLine = new Transform({
transform(chunk, encoding, callback) {
const lines = chunk.toString().split('
');
const processed = lines
.map(line => line.toUpperCase())
.join('
');
callback(null, processed);
}
});
await pipelineAsync(
fs.createReadStream(inputFile),
processLine,
fs.createWriteStream('output.csv')
);
}
SQL片段
安全Upsert模式
-- 片段:Upsert(插入或更新)
-- 类别:数据库
-- 标签:sql, upsert, postgresql
-- PostgreSQL
INSERT INTO users (id, email, name, updated_at)
VALUES (1, 'user@example.com', 'John Doe', NOW())
ON CONFLICT (id)
DO UPDATE SET
email = EXCLUDED.email,
name = EXCLUDED.name,
updated_at = NOW()
RETURNING *;
-- 多行upsert
INSERT INTO products (sku, name, price)
VALUES
('SKU001', 'Product 1', 29.99),
('SKU002', 'Product 2', 39.99)
ON CONFLICT (sku)
DO UPDATE SET
name = EXCLUDED.name,
price = EXCLUDED.price,
updated_at = NOW();
分页查询
-- 片段:高效分页
-- 类别:数据库
-- 标签:sql, pagination, performance
-- 基于偏移(简单但对于大偏移较慢)
SELECT *
FROM posts
ORDER BY created_at DESC
LIMIT 20 OFFSET 40; -- 第3页
-- 基于游标(更高效)
SELECT *
FROM posts
WHERE created_at < '2024-01-01 12:00:00'
ORDER BY created_at DESC
LIMIT 20;
-- 键集分页(最佳性能)
SELECT *
FROM posts
WHERE (created_at, id) < ('2024-01-01 12:00:00', 12345)
ORDER BY created_at DESC, id DESC
LIMIT 20;
最佳实践
片段组织
- 一致命名:使用清晰、描述性名称
- 全面标签:添加多个相关标签
- 版本跟踪:跟踪片段版本
- 依赖项:记录所需库
文档
- 使用示例:显示真实世界用法
- 参数文档:记录所有参数
- 边缘情况:提及限制和边缘情况
- 替代方案:建议相关模式
维护
- 定期审查:定期更新片段
- 测试片段:确保片段仍有效
- 弃用:标记过时片段
- 贡献:与团队共享有用片段
片段管理工具
基于文件的存储
snippets/
├── javascript/
│ ├── async/
│ │ ├── retry.js
│ │ └── debounce.js
│ └── react/
│ ├── hooks/
│ └── components/
├── python/
│ ├── decorators/
│ └── context-managers/
└── sql/
├── queries/
└── migrations/
元数据格式(frontmatter)
---
title: "异步重试与退避"
language: javascript
category: error-handling
tags: [async, retry, error-handling, resilience]
framework: nodejs
version: 1.2.0
author: team
created: 2024-01-15
updated: 2024-01-20
---
备注
- 保持片段专注和单一用途
- 在示例中包括错误处理
- 记录性能特征
- 保存前测试片段
- 使用一致的编码风格
- 为复杂逻辑添加注释
- 进行更改时对片段进行版本控制
- 在团队内共享片段
- 定期清理过时片段