index.ts 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  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) {
  10. if (e instanceof Error)
  11. return [e]
  12. return [new Error('unknown error')]
  13. }
  14. }
  15. export const getTextWidthWithCanvas = (text: string, font?: string) => {
  16. const canvas = document.createElement('canvas')
  17. const ctx = canvas.getContext('2d')
  18. if (ctx) {
  19. 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"'
  20. return Number(ctx.measureText(text).width.toFixed(2))
  21. }
  22. return 0
  23. }
  24. const chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_'
  25. export function randomString(length: number) {
  26. let result = ''
  27. for (let i = length; i > 0; --i) result += chars[Math.floor(Math.random() * chars.length)]
  28. return result
  29. }
  30. export const getPurifyHref = (href: string) => {
  31. if (!href)
  32. return ''
  33. return escape(href)
  34. }
  35. export async function fetchWithRetry<T = any>(fn: Promise<T>, retries = 3): Promise<[Error] | [null, T]> {
  36. const [error, res] = await asyncRunSafe(fn)
  37. if (error) {
  38. if (retries > 0) {
  39. const res = await fetchWithRetry(fn, retries - 1)
  40. return res
  41. }
  42. else {
  43. if (error instanceof Error)
  44. return [error]
  45. return [new Error('unknown error')]
  46. }
  47. }
  48. else {
  49. return [null, res]
  50. }
  51. }