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

背景

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

遇到的問題

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

曲折的解決問題

step1

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

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

因?yàn)樵恢С种苯荧@取AsyncFunction穿铆,所以這里通過獲取async函數(shù)的構(gòu)造函數(shù)原型來獲取。
屁顛屁顛地跑去項(xiàng)目里用了一下斋荞,發(fā)現(xiàn)并沒有生效荞雏。

step2

開始脫離項(xiàng)目寫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

思考項(xiàng)目中用到了什么凤优,在想不會(huì)是webpack的鍋吧,但不能確定蜈彼。
于是回到項(xiàng)目筑辨,在瀏覽器報(bào)錯(cuò)后跳轉(zhuǎn)到報(bào)錯(cuò)的地方,是一個(gè)VMxxxx文件幸逆,截屏如下:

image.png

看到我自己的code前面被包了一層(function anonymous(){mycode})棍辕,猜想會(huì)不會(huì)跟這個(gè)有關(guān),但查了一下VMxxxx文件是js虛擬機(jī)編譯生成的文件还绘,照理說瀏覽器對(duì)同樣的代碼執(zhí)行流程都一樣楚昭,肯定都會(huì)經(jīng)歷編譯階段,既然在瀏覽器直接執(zhí)行不報(bào)錯(cuò)蚕甥,應(yīng)該跟這個(gè)無關(guān)哪替。

接著打斷點(diǎn)看看發(fā)生了什么。在報(bào)錯(cuò)的語句前打了斷點(diǎn)菇怀,然后在瀏覽器定義AsyncFunction并執(zhí)行,并沒有報(bào)錯(cuò)晌块。

image.png

image.png

正當(dāng)我納悶的時(shí)候爱沟,想著應(yīng)該對(duì)比一下項(xiàng)目里的AsyncFunction和我直接在瀏覽器定義的AsyncFunction有什么區(qū)別,就分別打印了一下匆背,終于找到了原因呼伸,項(xiàng)目里的AsyncFunction不知道啥時(shí)候悄悄變成了Function,怪不得又不能用await了。

image.png

step4

所以思考AsyncFunction為什么會(huì)變成Function括享。似乎只有webpack可能產(chǎn)生影響搂根,于是在另一個(gè)用webpack打包的項(xiàng)目中嘗試了一下,也報(bào)一樣的錯(cuò)铃辖,基本上鎖定是webpack的問題了剩愧。想到我們一般在項(xiàng)目里會(huì)用babeljs編譯成es5,而es5不認(rèn)識(shí)async娇斩,自然也不認(rèn)識(shí)它的原型仁卷,所以我把AsyncFunction的定義放到一個(gè)單獨(dú)的文件,不讓webpack編譯犬第,終于可以順利執(zhí)行了锦积!

結(jié)論

  1. 如果在原生支持es7的項(xiàng)目(不經(jīng)過babel等轉(zhuǎn)義)中使用,直接通過const AsyncFunction = Object.getPrototypeOf(async function(){}).constructor;獲取到原型歉嗓,就可以像new Function一樣使用了
  2. 目前前端工程化項(xiàng)目為了兼容性丰介,一般都會(huì)用到babel轉(zhuǎn)義,這時(shí)候就需要先把const AsyncFunction = Object.getPrototypeOf(async function(){}).constructor;這個(gè)定義放到單獨(dú)的文件鉴分,并且不轉(zhuǎn)義該文件哮幢,才能在執(zhí)行的時(shí)候獲取正確的類型。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末冠场,一起剝皮案震驚了整個(gè)濱河市家浇,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌碴裙,老刑警劉巖钢悲,帶你破解...
    沈念sama閱讀 218,941評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異舔株,居然都是意外死亡莺琳,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門载慈,熙熙樓的掌柜王于貴愁眉苦臉地迎上來惭等,“玉大人,你說我怎么就攤上這事办铡〈亲觯” “怎么了?”我有些...
    開封第一講書人閱讀 165,345評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵寡具,是天一觀的道長秤茅。 經(jīng)常有香客問我,道長童叠,這世上最難降的妖魔是什么框喳? 我笑而不...
    開封第一講書人閱讀 58,851評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上五垮,老公的妹妹穿的比我還像新娘乍惊。我一直安慰自己,他們只是感情好放仗,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評(píng)論 6 392
  • 文/花漫 我一把揭開白布润绎。 她就那樣靜靜地躺著,像睡著了一般匙监。 火紅的嫁衣襯著肌膚如雪凡橱。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,688評(píng)論 1 305
  • 那天亭姥,我揣著相機(jī)與錄音稼钩,去河邊找鬼。 笑死达罗,一個(gè)胖子當(dāng)著我的面吹牛坝撑,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播粮揉,決...
    沈念sama閱讀 40,414評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼巡李,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了扶认?” 一聲冷哼從身側(cè)響起侨拦,我...
    開封第一講書人閱讀 39,319評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎辐宾,沒想到半個(gè)月后狱从,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,775評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡叠纹,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年季研,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片誉察。...
    茶點(diǎn)故事閱讀 40,096評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡与涡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出持偏,到底是詐尸還是另有隱情驼卖,我是刑警寧澤,帶...
    沈念sama閱讀 35,789評(píng)論 5 346
  • 正文 年R本政府宣布鸿秆,位于F島的核電站款慨,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏谬莹。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望附帽。 院中可真熱鬧埠戳,春花似錦、人聲如沸蕉扮。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽喳钟。三九已至屁使,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間奔则,已是汗流浹背蛮寂。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評(píng)論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留易茬,地道東北人酬蹋。 一個(gè)月前我還...
    沈念sama閱讀 48,308評(píng)論 3 372
  • 正文 我出身青樓,卻偏偏與公主長得像抽莱,于是被迫代替她去往敵國和親范抓。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容