来自@Arun Killu的答案是一个很好的片段,如果你知道发生了什么,但是没有人解释原始代码上的错误是什么。对于使用async和Promise调用的人来说,这个错误是很明显的,但对于正在学习或没有经验的人来说,就不那么清楚了。
这里有一个简单的解释。
糟糕的代码
var blob = items[i].getAsFile();
var reader = new FileReader();
reader.onload = function(event){
console.log(event.target.result)
}; // data url!
var source = reader.readAsBinaryString(blob);
上面的代码试图捕获源变量上的二进制字符串,但是FileReader.readAsBinaryString()返回undefined。这是因为无论何时触发onload事件,结果都是可用的。正如我们所看到的,他试图console.log event.target.result值,这是一个错误的方法。
好的代码
下面是一步一步的实现:
// 1. Create a FileReader instance
const reader = new FileReader()
// 2. Add a handler for the 'onload' event
reader.onload = (e) => {
// 5. Get the result when the 'onload' event is triggered.
const base64data = reader.result
console.log({base64data})
}
// 3. Add a handler for the 'onerror' event
reader.onerror = () => {
console.log('error')
}
// 4. Call 'readAsDataURL' method
reader.readAsDataURL(imageBlob)
正如你所看到的,最后一步是5,这是因为它是一个异步调用。
下面是一个工作示例:
const url = 'https://i.stack.imgur.com/RRuCp.png'
const fetchImage = async url => {
const response = await fetch(url, {mode: 'no-cors',})
const blob = await response.blob()
return blob
}
const loadImage = async () => {
const imageBlob = await fetchImage(url)
const reader = new FileReader()
reader.onload = () => {
const base64data = reader.result
console.log({base64data})
}
reader.onerror = () => {
console.log('error')
}
reader.readAsDataURL(imageBlob)
}
loadImage()
Teo,异步是什么意思?
年轻的学徒,异步意味着我们不知道结果什么时候会准备好,它在每个系统中都是不同的,这取决于过程有多重或复杂,它也可以发现一些根本不会产生任何结果的错误。
因此,如果一个进程是异步的,使用async方法封装它是一个很好的实践,并返回一个像这样的Promise:
const blobToBase64 = async blob => {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => resolve(reader.result)
reader.error = (err) => reject(err)
reader.readAsDataURL(blob)
})
}
好吧,泰奥,但是什么是承诺?
小伙子,问得好。Promise对象表示异步操作的最终完成(或失败)及其结果值。换句话说,它会告诉我们结果是否准备好了,并会给我们它的值,否则会返回一个错误。
上面的代码显示了一个函数blobToBase64,它将返回一个Promise。这意味着这个函数将返回reader。结果当它准备好了。
如何将其集成到代码中?
超级简单,只需将所有FileReader替换为上面定义的函数blobToBase64并像这样调用它imageBase64 = await blobToBase64(imageBlob)
检查这个片段:
const url = 'https://i.stack.imgur.com/RRuCp.png'
const fetchImage = async url => {
const response = await fetch(url, {
mode: 'no-cors',
})
const blob = await response.blob()
return blob
}
const blobToBase64 = async blob => {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => resolve(reader.result)
reader.error = (err) => reject(err)
reader.readAsDataURL(blob)
})
}
const loadImage = async() => {
const imageBlob = await fetchImage(url)
const imageBase64 = await blobToBase64(imageBlob)
console.log({imageBase64})
}
loadImage()