javascript - 如何将异步函数值传递给事件处理程序
问题描述
我正在获取样式表并将所有 CSS 变量替换为当用户根据需要更改颜色时它对应的实际十六进制值。
我创建了一个事件处理程序,以便当用户单击下载按钮时,他/她选择的所有颜色都将保存在样式表中,但它似乎不起作用。我知道这是我对整个承诺的理解的问题async await
我做了什么。
const fetchStyleSheet = async () => {
const res = await fetch("./themes/prism.css");
const orig_css = await res.text();
let updated_css = orig_css;
const regexp = /(?:var\(--)[a-zA-z\-]*(?:\))/g;
let cssVars = orig_css.matchAll(regexp);
cssVars = Array.from(cssVars).flat();
console.log(cssVars)
for await (const variable of cssVars) {
const trimmedVar = variable.slice(6, -1)
const styles = getComputedStyle(document.documentElement)
const value = String(styles.getPropertyValue(`--${trimmedVar}`)).trim()
updated_css = updated_css.replace(variable, value);
}
console.log(updated_css)
return updated_css
}
const main = async () => {
const downloadBtn = document.getElementById('download-btn')
downloadBtn.addEventListener('click', () => {
const updated_css = fetchStyleSheet()
downloadBtn.setAttribute('href', 'data:application/octet-stream;charset=utf-8,' + encodeURIComponent(updated_css))
downloadBtn.setAttribute('download', 'prism-theme.css')
})
}
main()
我不能await
,updated_css
因为它属于点击事件的回调,这是一个新功能。
然后我做了以下认为它会起作用,因为它是顶级的。
const downloadBtn = document.getElementById('download-btn')
downloadBtn.addEventListener('click', async () => {
const updated_css = await fetchStyleSheet()
downloadBtn.setAttribute('href', 'data:application/octet-stream;charset=utf-8,' + encodeURIComponent(updated_css))
downloadBtn.setAttribute('download', 'prism-theme.css')
})
这给了我以下错误TypeError: NetworkError when attempting to fetch resource.
我知道调用fetchStyleSheet()
一开始只返回一个promise对象并且要获取值(即updated_css
),我需要跟随它.then()
或await
它。
解决方案
这await
是处理fetchStyleSheet()
返回承诺的调用的正确方法,您的问题是单击链接会尝试href
立即遵循该属性 -在您将其设置为该数据 url 之前。相反,您需要做的是阻止默认操作,异步执行您的操作,然后在完成后重新触发单击。也不要忘记处理可能的异常:
const downloadBtn = document.getElementById('download-btn')
downloadBtn.addEventListener('click', async (event) => {
if (!e.isTrusted) return // do nothing on the second run
try {
event.preventDefault()
const updated_css = await fetchStyleSheet()
downloadBtn.setAttribute('href', 'data:application/octet-stream;charset=utf-8,' + encodeURIComponent(updated_css))
downloadBtn.setAttribute('download', 'prism-theme.css')
downloadBtn.click() // simulate a new click
} catch(err) {
console.error(err) // or alert it, or put the message on the page
}
})
推荐阅读
- android - 在 Android Studio/Flutter 中从 Firebase 数据库创建特定集合的字符串列表
- python - 如何使用 gensim 和 pytorch 创建意图分类器(使用 LSTM NN)?
- javascript - 如何在 JavaScript 中将多行字符串值转换为合法的 JSON 字符串变量?
- javascript - 仅打印负数及其和循环和数组
- php - Composer 找不到类...但找到同级文件
- c++ - 反斜杠和引号不计入字符串长度?
- kotlin - Kotlin flatmap 解压数据类列表
- python - 是否有错误的解决方案:condarc invalid yaml 和 ConfigurationLoadError: Unable to load configuration file?
- angular - 动态地将文本墙上的每个单词转换为 Angular 7 中调用角度函数的(点击) - 使用什么?
- spring - 对于 Kotlin 未经检查的异常,Spring 不会回滚事务