前端二维码生成

7 阅读2分钟

📋 二维码生成

我们使用的是 qrcode 库(通过 pnpm add qrcode 安装),它提供了两种调用方式:

核心原理

QRCode.toDataURL() 函数的实现逻辑:

  • 传入回调函数时:同步执行模式

    • 立即调用 QRCode.create() 同步生成二维码数据
    • 然后立即调用你的回调函数
    • 整个过程没有异步等待,是真正的同步执行
  • 不传回调函数时:异步执行模式

    • 返回 Promise 对象
    • 内部仍然同步生成数据,但通过 Promise 包装实现异步接口

源码关键部分:

// lib/server.js
exports.toDataURL = function toDataURL(text, opts, cb) {
  const params = checkParams(text, opts, cb)
  const renderer = getRendererFromType(params.opts.type)
  return render(renderer.renderToDataURL, text, params)
}
​
// render 函数
function render(renderFunc, text, params) {
  if (params.cb) {
    // 有回调函数:同步执行
    const data = QRCode.create(text, params.opts)  // 同步生成
    return renderFunc(data, params.opts, params.cb)  // 立即调用回调
  } else {
    // 无回调函数:返回 Promise(异步包装)
    return new Promise(...)
  }
}

使用方式

1. 同步方式(传入回调函数)

QRCode.toDataURL('你的文本', { type: 'image/png' }, (err, dataUrl) => {
  if (err) throw err
  console.log('立即获得结果:', dataUrl)
  // 这里的代码会马上执行,不需要等待
})
​
// 验证同步特性
console.log('开始')
QRCode.toDataURL('test', {}, (err, url) => {
  console.log('回调执行')  // 实际会先打印
})
console.log('回调注册后')  // 实际会后打印
// 输出顺序:开始 → 回调执行 → 回调注册后

2. 异步方式(Promise/不传回调函数)

// 方式一:Promise.then()
QRCode.toDataURL('你的文本', { type: 'image/png' })
  .then(dataUrl => console.log('异步获得结果:', dataUrl))
  .catch(err => console.error('生成失败:', err))
​
// 方式二:async/await(推荐)
async function generateQRCode() {
  try {
    const dataUrl = await QRCode.toDataURL('你的文本', { type: 'image/png' })
    console.log('异步获得结果:', dataUrl)
    return dataUrl
  } catch (err) {
    console.error('生成失败:', err)
    throw err
  }
}

总结

  • 同步模式:传入回调函数,立即执行,适合简单场景
  • 异步模式:不传回调函数,返回 Promise,适合现代异步编程

无论哪种方式,dataUrl 都是 Base64 编码的图像字符串,格式为 data:image/png;base64,...,可直接用于 <img> 标签显示二维码。