📋 二维码生成
我们使用的是 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> 标签显示二维码。