index.ts 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. import { escape } from 'lodash-es'
  2. export const sleep = (ms: number) => {
  3. return new Promise(resolve => setTimeout(resolve, ms))
  4. }
  5. export async function asyncRunSafe<T = any>(fn: Promise<T>): Promise<[Error] | [null, T]> {
  6. try {
  7. return [null, await fn]
  8. }
  9. catch (e: any) {
  10. return [e || new Error('unknown error')]
  11. }
  12. }
  13. export const getTextWidthWithCanvas = (text: string, font?: string) => {
  14. const canvas = document.createElement('canvas')
  15. const ctx = canvas.getContext('2d')
  16. if (ctx) {
  17. ctx.font = font ?? '12px Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"'
  18. return Number(ctx.measureText(text).width.toFixed(2))
  19. }
  20. return 0
  21. }
  22. const chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_'
  23. export function randomString(length: number) {
  24. let result = ''
  25. for (let i = length; i > 0; --i) result += chars[Math.floor(Math.random() * chars.length)]
  26. return result
  27. }
  28. export const getPurifyHref = (href: string) => {
  29. if (!href)
  30. return ''
  31. return escape(href)
  32. }
  33. export async function fetchWithRetry<T = any>(fn: Promise<T>, retries = 3): Promise<[Error] | [null, T]> {
  34. const [error, res] = await asyncRunSafe(fn)
  35. if (error) {
  36. if (retries > 0) {
  37. const res = await fetchWithRetry(fn, retries - 1)
  38. return res
  39. }
  40. else {
  41. if (error instanceof Error)
  42. return [error]
  43. return [new Error('unknown error')]
  44. }
  45. }
  46. else {
  47. return [null, res]
  48. }
  49. }