Chrome扩展Service Worker顶层使用await报错的解决方法
Chrome扩展Service Worker中await语法错误的解决办法
问题情况
在Chrome扩展的Service Worker脚本顶层写了这段代码:
await tmrs=chrome.storage.local.get("tmrs"); console.log(tmrs); await data=chrome.storage.local.get("Auto_Select_051969"); console.log(data); if (data==null) { store_data(); await data=chrome.storage.local.get("Auto_Select_051969"); }
运行后直接报错:
Uncaught SyntaxError: await is only valid in async functions and the top level bodies of modules
想搞清楚:
- 为啥有这个限制?
- 怎么修复?
- 用匿名async函数是不是可行?比如我写的这段更新后的代码有问题吗?
(async () => { let tmrs=await chrome.storage.local.get("tmrs"); })(); console.log(tmrs);
限制原因
Chrome扩展的Service Worker默认不是ES模块模式,顶层作用域不能直接用await——await只有两个合法使用场景:要么在async标记的函数内部,要么在ES模块的顶层作用域里。普通脚本的顶层不属于这两种情况,所以直接写await就会触发语法错误。
修复方案
方案1:用自执行async匿名函数(可行,但要注意作用域)
你想的匿名async函数思路是对的,但你写的代码有问题:tmrs是函数内部的局部变量,外面的console.log(tmrs)根本拿不到值。得把所有依赖异步结果的逻辑都放进函数里:
(async () => { let tmrs = await chrome.storage.local.get("tmrs"); console.log(tmrs); let data = await chrome.storage.local.get("Auto_Select_051969"); console.log(data); // 注意:chrome.storage.local.get返回的是对象,不存在的键会返回空对象,不是null if (!data || Object.keys(data).length === 0) { store_data(); data = await chrome.storage.local.get("Auto_Select_051969"); } })();
方案2:把Service Worker改成ES模块(更推荐)
在manifest.json里把Service Worker配置成模块模式,这样就能直接在顶层用await:
- 修改manifest.json的background配置:
{ "background": { "service_worker": "background.js", "type": "module" } }
- 然后在Service Worker脚本里直接写:
let tmrs = await chrome.storage.local.get("tmrs"); console.log(tmrs); let data = await chrome.storage.local.get("Auto_Select_051969"); console.log(data); if (!data || Object.keys(data).length === 0) { store_data(); data = await chrome.storage.local.get("Auto_Select_051969"); }
这种写法更清爽,也不用纠结作用域问题。
关于匿名async函数的有效性
匿名自执行async函数是有效的解决办法,但必须把所有需要用到异步结果的代码都放在函数内部——不然外部代码会比异步操作先执行,拿不到正确的值。你之前写的console.log(tmrs)在函数外面,会输出undefined,这是错的。
内容的提问来源于stack exchange,提问作者Wt Riker
相关产品推荐
相关产品推荐

