如何在new Function中使用await函數(shù)

背景

我司做了一個可視化大屏的項目,但基于配置的組件不可能窮盡所有情況,因此計劃開發(fā)js交互功能,讓用戶可以通過js進行二次開發(fā)。

遇到的問題

直接用new Function()去執(zhí)行用戶的代碼,一開始寫靜態(tài)數(shù)據(jù)demo的時候沒發(fā)現(xiàn)有啥問題。但當我去請求動態(tài)數(shù)據(jù)的時候,發(fā)現(xiàn)我很想用await,然而直接使用會報SyntaxError: await is only valid in async function at new Function (<anonymous>)的錯。

曲折的解決問題

step1

google查詢如何在new Function里使用async,查到了這篇文章,大喜。主要代碼:

const AsyncFunction = Object.getPrototypeOf(async function(){}).constructor;
const fetchPage = new AsyncFunction("url", "return await fetch(url);");
fetchPage("/").then(response => { ... });

因為原生不支持直接獲取AsyncFunction,所以這里通過獲取async函數(shù)的構造函數(shù)原型來獲取。
屁顛屁顛地跑去項目里用了一下,發(fā)現(xiàn)并沒有生效。

step2

開始脫離項目寫demo,把問題最小化。代碼如下:

function test() {
  const AsyncFunction = Object.getPrototypeOf(async function () {}).constructor;
  const code =
    'const name = await Promise.resolve(stage.name); \n console.log(name)';
  const func = new AsyncFunction('stage', code);
  func({ name: '1' }).then((response) => {
    console.log(response);
  });
}
test();

在node.js和chrome環(huán)境下均可以正確執(zhí)行

step3

思考項目中用到了什么,在想不會是webpack的鍋吧,但不能確定。
于是回到項目,在瀏覽器報錯后跳轉到報錯的地方,是一個VMxxxx文件,截屏如下:

image.png

看到我自己的code前面被包了一層(function anonymous(){mycode}),猜想會不會跟這個有關,但查了一下VMxxxx文件是js虛擬機編譯生成的文件,照理說瀏覽器對同樣的代碼執(zhí)行流程都一樣,肯定都會經歷編譯階段,既然在瀏覽器直接執(zhí)行不報錯,應該跟這個無關。

接著打斷點看看發(fā)生了什么。在報錯的語句前打了斷點,然后在瀏覽器定義AsyncFunction并執(zhí)行,并沒有報錯。

image.png

image.png

正當我納悶的時候,想著應該對比一下項目里的AsyncFunction和我直接在瀏覽器定義的AsyncFunction有什么區(qū)別,就分別打印了一下,終于找到了原因,項目里的AsyncFunction不知道啥時候悄悄變成了Function,怪不得又不能用await了。

image.png

step4

所以思考AsyncFunction為什么會變成Function。似乎只有webpack可能產生影響,于是在另一個用webpack打包的項目中嘗試了一下,也報一樣的錯,基本上鎖定是webpack的問題了。想到我們一般在項目里會用babeljs編譯成es5,而es5不認識async,自然也不認識它的原型,所以我把AsyncFunction的定義放到一個單獨的文件,不讓webpack編譯,終于可以順利執(zhí)行了!

結論

  1. 如果在原生支持es7的項目(不經過babel等轉義)中使用,直接通過const AsyncFunction = Object.getPrototypeOf(async function(){}).constructor;獲取到原型,就可以像new Function一樣使用了
  2. 目前前端工程化項目為了兼容性,一般都會用到babel轉義,這時候就需要先把const AsyncFunction = Object.getPrototypeOf(async function(){}).constructor;這個定義放到單獨的文件,并且不轉義該文件,才能在執(zhí)行的時候獲取正確的類型。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容