前端異步面試題大全

以下題目是根據(jù)網(wǎng)上多份面經(jīng)收集而來的蘑辑,題目相同意味著被問的頻率比較高(x3表示有三份面經(jīng)被問)沧侥,有問題歡迎留言討論爸邢,喜歡可以點贊關(guān)注

1咏花、瀏覽器架構(gòu)

1.用戶界面
2.瀏覽器引擎(負(fù)責(zé)窗口管理、Tab進(jìn)程管理等)
3.渲染引擎(有叫內(nèi)核疙驾,負(fù)責(zé)HTML解析桐玻、頁面渲染)
4.JS引擎(JS解釋器,如Chrome和Nodejs采用的V8)

2荆萤、JS異步解決方案的發(fā)展歷程以及優(yōu)缺點

https://blog.csdn.net/lunahaijiao/article/details/87167417
1、回調(diào)函數(shù)(callback)

setTimeout(() => {
    // callback 函數(shù)體
}, 1000)

缺點:回調(diào)地獄铣卡,不能用 try catch 捕獲錯誤链韭,不能 return
優(yōu)點:解決了同步的問題(只要有一個任務(wù)耗時很長,后面的任務(wù)都必須排隊等著煮落,會拖延整個程序的執(zhí)行敞峭。)

2. Promise
Promise就是為了解決callback的問題而產(chǎn)生的。
Promise 實現(xiàn)了鏈?zhǔn)秸{(diào)用蝉仇,也就是說每次 then 后返回的都是一個全新 Promise旋讹,如果我們在 then 中 return ,return 的結(jié)果會被 Promise.resolve() 包裝
優(yōu)點:解決了回調(diào)地獄的問題

ajax('XXX1')
  .then(res => {
      // 操作邏輯
      return ajax('XXX2')
  }).then(res => {
      // 操作邏輯
      return ajax('XXX3')
  }).then(res => {
      // 操作邏輯
  })

缺點:無法取消 Promise 轿衔,錯誤需要通過回調(diào)函數(shù)來捕獲

3. Generator
特點:可以控制函數(shù)的執(zhí)行沉迹,可以配合 co 函數(shù)庫使用

function *fetch() {
    yield ajax('XXX1', () => {})
    yield ajax('XXX2', () => {})
    yield ajax('XXX3', () => {})
}
let it = fetch()
let result1 = it.next()
let result2 = it.next()
let result3 = it.next()

4. Async/await
async、await 是異步的終極解決方案
優(yōu)點是:代碼清晰害驹,不用像 Promise 寫一大堆 then 鏈鞭呕,處理了回調(diào)地獄的問題
缺點:await 將異步代碼改造成同步代碼,如果多個異步操作沒有依賴性而使用 await 會導(dǎo)致性能上的降低宛官。

async function test() {
  // 以下代碼沒有依賴性的話葫松,完全可以使用 Promise.all 的方式
  // 如果有依賴性的話瓦糕,其實就是解決回調(diào)地獄的例子了
  await fetch('XXX1')
  await fetch('XXX2')
  await fetch('XXX3')
}

下面來看一個使用 await 的例子:

let a = 0
let b = async () => {
  a = a + await 10
  console.log('2', a) // -> '2' 10
}
b()
a++
console.log('1', a) // -> '1' 1

對于以上代碼你可能會有疑惑,讓我來解釋下原因

首先函數(shù) b 先執(zhí)行腋么,在執(zhí)行到 await 10 之前變量 a 還是 0咕娄,因為 await 內(nèi)部實現(xiàn)了 generator ,generator 會保留堆棧中東西珊擂,所以這時候 a = 0 被保存了下來
因為 await 是異步操作圣勒,后來的表達(dá)式不返回 Promise 的話,就會包裝成 Promise.reslove(返回值)未玻,然后會去執(zhí)行函數(shù)外的同步代碼
同步代碼執(zhí)行完畢后開始執(zhí)行異步代碼灾而,將保存下來的值拿出來使用,這時候 a = 0 + 10
上述解釋中提到了 await 內(nèi)部實現(xiàn)了 generator扳剿,其實 await 就是 generator 加上 Promise的語法糖旁趟,且內(nèi)部實現(xiàn)了自動執(zhí)行 generator。如果你熟悉 co 的話庇绽,其實自己就可以實現(xiàn)這樣的語法糖锡搜。

3、介紹各種異步方案x3

同2

4瞧掺、JS執(zhí)行過程中分為哪些階段

https://blog.csdn.net/weixin_34009794/article/details/91431985

1耕餐、語法分析 2、預(yù)編譯階段 3辟狈、執(zhí)行階段

一. 語法分析
分析該js腳本代碼塊的語法是否正確肠缔,如果出現(xiàn)不正確,則向外拋出一個語法錯誤(SyntaxError)哼转,停止該js代碼塊的執(zhí)行明未,然后繼續(xù)查找并加載下一個代碼塊;如果語法正確壹蔓,則進(jìn)入預(yù)編譯階段趟妥。下面階段的代碼執(zhí)行不會再進(jìn)行語法校驗,語法分析在代碼塊加載完畢時統(tǒng)一檢驗語法佣蓉。

二. 預(yù)編譯階段

1披摄、js的運行環(huán)境
每進(jìn)入一個不同的運行環(huán)境都會創(chuàng)建一個相應(yīng)的執(zhí)行上下文(Execution Context),那么在一段JS程序中一般都會創(chuàng)建多個執(zhí)行上下文勇凭,js引擎會以棧的方式對這些執(zhí)行上下文進(jìn)行處理疚膊,形成函數(shù)調(diào)用棧(call stack),棧底永遠(yuǎn)是全局執(zhí)行上下文(Global Execution Context)虾标,棧頂則永遠(yuǎn)是當(dāng)前執(zhí)行上下文酿联。

2、函數(shù)調(diào)用棧/執(zhí)行棧
調(diào)用棧,也叫執(zhí)行棧贞让,具有LIFO(后進(jìn)先出)結(jié)構(gòu)周崭,用于存儲在代碼執(zhí)行期間創(chuàng)建的所有執(zhí)行上下文。首次運行JS代碼時喳张,會創(chuàng)建一個全局執(zhí)行上下文并Push到當(dāng)前的執(zhí)行棧中续镇。每當(dāng)發(fā)生函數(shù)調(diào)用,引擎都會為該函數(shù)創(chuàng)建一個新的函數(shù)執(zhí)行上下文并Push到當(dāng)前執(zhí)行棧的棧頂销部。當(dāng)棧頂函數(shù)運行完成后摸航,其對應(yīng)的函數(shù)執(zhí)行上下文將會從執(zhí)行棧中Pop出,上下文控制權(quán)將移到當(dāng)前執(zhí)行棧的下一個執(zhí)行上下文舅桩。

3酱虎、執(zhí)行上下文的創(chuàng)建
執(zhí)行上下文可理解為當(dāng)前的執(zhí)行環(huán)境,與該運行環(huán)境相對應(yīng)擂涛,具體分類如上面所說分為全局執(zhí)行上下文和函數(shù)執(zhí)行上下文读串。創(chuàng)建執(zhí)行上下文的三部曲:①創(chuàng)建變量對象(Variable Object)②建立作用域鏈(Scope Chain)③確定this的指向

三. 執(zhí)行階段

  1. 網(wǎng)頁的線程
  2. 宏任務(wù)
  3. 事件循環(huán)
  4. 微任務(wù)
5、定時器的執(zhí)行順序

長話短說撒妈,我們需要記住的是:因為js是單線程的恢暖,瀏覽器遇到setTimeout或者setInterval會先執(zhí)行完當(dāng)前的代碼塊,在此之前會把定時器推入瀏覽器的待執(zhí)行事件隊列里面狰右,等到瀏覽器執(zhí)行完當(dāng)前代碼之后會看一下事件隊列里面有沒有任務(wù)杰捂,有的話才執(zhí)行定時器的代碼。 所以即使把定時器的時間設(shè)置為0還是會先執(zhí)行當(dāng)前的一些代碼棋蚌。劃重點:簡單來說就是瀏覽器會限制性當(dāng)前代碼嫁佳,等當(dāng)前的代碼執(zhí)行完了,會看一下有沒有待執(zhí)行的事件谷暮,如果有才執(zhí)行定時器的代碼

6蒿往、同步與異步的執(zhí)行順序

1、不管是同步還是異步坷备,js都會按順序執(zhí)行,只是不等待異步的執(zhí)行結(jié)果而已(并不是遇到異步的就繞過不執(zhí)行情臭,別蒙了)
2省撑、同步的任務(wù)沒有優(yōu)先級之分,異步執(zhí)行有優(yōu)先級俯在,先執(zhí)行微任務(wù)(microtask隊列)竟秫,再執(zhí)行宏任務(wù)(macrotask隊列),同級別按順序執(zhí)行

7跷乐、如何處理異常捕獲

https://juejin.im/post/5cc15de5e51d456e68659340

JS中的異常捕獲(目的:把拋出的錯誤捕獲到肥败,不讓其阻斷瀏覽器的繼續(xù)執(zhí)行)一般寫法如下:

try{
    //需要執(zhí)行的JS代碼(可能會報錯)
}catch(e){
    //try中代碼報錯,會執(zhí)行catch
}finally{
    //不管try中的代碼成功還是失敗都會執(zhí)行
}

但是宏任務(wù)的回調(diào)函數(shù)中的錯誤無法捕獲

    function main() {
        try {
            setTimeout(() => {
                throw new Error('async error')
            }, 1000)
        } catch (e) {
            console.log(e, 'err')
        }
    }
    main();
8、setInterval需要注意的點

window.setInterval(para1,para2);
一共有以下幾種形式:
window.setInterval(function(){alert('xxx')},1000); para1為匿名函數(shù)的形式馒稍,
window.setInterval("myFunc()",1000); para1為一個字符串皿哨,而且這個字符串是一個已經(jīng)寫好的函數(shù)的名稱。
以上這兩種可以正常運行纽谒,
1证膨、第一個參數(shù)必須是一個方法且必須加引號,否則只會執(zhí)行一次
2鼓黔、不能傳遞帶參數(shù)的函數(shù)
如:setInterval(function(args), 600);
3央勒、setInterval 周期性的調(diào)用函數(shù)或計算方法,關(guān)閉用clearInterval 澳化。setInterval 和clearInterval 是一對一的關(guān)系崔步。比如想要對同一個按鈕在不同場景中,使用周期性的調(diào)用不同的函數(shù)缎谷,那么需要先關(guān)掉上一個setInterval井濒,再設(shè)定另一個setInterval不然上一個setInterval仍然在進(jìn)行著。

9慎陵、定時器為什么是不精確的

因為定時器是異步的眼虱,要等到同步任務(wù)執(zhí)行完之后,才會去執(zhí)行異步的任務(wù)席纽,即使setTimeout(0)中時間為0也不是立馬執(zhí)行捏悬。再者w3c在HTML標(biāo)準(zhǔn)中規(guī)定,要求setTimeout時間低于4ms的都按4ms來算润梯。

解決方法: 使用 web Worker 將定時函數(shù)作為獨立線程執(zhí)行

10过牙、setTimeout(1)和setTimeout(2)之間的區(qū)別

返回一個 ID(數(shù)字),可以將這個ID傳遞給 clearTimeout() 來取消執(zhí)行纺铭。setTimeout(1)的id數(shù)比setTimeout(2)的id數(shù)要大1

11寇钉、如何解決同步調(diào)用代碼耗時太高的問題

①異步處理②web worker 開辟線程處理

12、異步請求舶赔,低版本fetch如何低版本適配

https://www.cnblogs.com/wonyun/p/fetch_polyfill_timeout_jsonp_cookie_progress.html

說道fetch就不得不提XMLHttpRequest了扫倡,XHR在發(fā)送web請求時需要開發(fā)者配置相關(guān)請求信息和成功后的回調(diào),盡管開發(fā)者只關(guān)心請求成功后的業(yè)務(wù)處理竟纳,但是也要配置其他繁瑣內(nèi)容撵溃,導(dǎo)致配置和調(diào)用比較混亂,也不符合關(guān)注分離的原則锥累;fetch的出現(xiàn)正是為了解決XHR存在的這些問題缘挑。例如下面代碼:

fetch(url).then(function(response) {
  return response.json();
}).then(function(data) {
  console.log(data);
}).catch(function(e) {
  console.log("Oops, error");
});

上面這段代碼讓開發(fā)者只關(guān)注請求成功后的業(yè)務(wù)邏輯處理,其他的不用關(guān)心桶略,相當(dāng)簡單语淘;也比較符合現(xiàn)代Promise形式诲宇,比較友好。fetch是基于Promise設(shè)計的惶翻,從上面代碼也能看得出來姑蓝,這就要求fetch要配合Promise一起使用。正是這種設(shè)計维贺,fetch所帶來的優(yōu)點正如傳統(tǒng) Ajax 已死它掂,F(xiàn)etch 永生總結(jié)的一樣:

  • 語法簡單,更加語義化
  • 基于標(biāo)準(zhǔn)的Promise實現(xiàn)溯泣,支持async/await
  • 使用isomorphic-fetch可以方便同構(gòu)

不過話說回來虐秋,fetch雖然有很多優(yōu)點,但是使用fetch來進(jìn)行項目開發(fā)時垃沦,也是有一些常見問題的客给,下面就來說說fetch使用的常見問題。

1肢簿、fetch兼容性
在各個瀏覽器低版本的情況下都是不被支持的靶剑。那么問題來了,如何在所有瀏覽器中通用fetch呢池充,當(dāng)然就要考慮fetch的polyfill了桩引。上面說過,fetch是基于Promise來實現(xiàn)的收夸,所以在低版本瀏覽器中Promise可能也未被原生支持坑匠,所以還需要Promise的polyfill;大多數(shù)情況下卧惜,實現(xiàn)fetch的polyfill需要涉及到的:* promise的polyfill厘灼,例如es6-promise、babel-polyfill提供的promise實現(xiàn)咽瓷。* fetch的polyfill實現(xiàn)设凹,例如isomorphic-fetch和whatwg-fetch 這樣是否就可以安全的使用fetch來進(jìn)行前后端通信了?上面說了在大多數(shù)情況下是這樣茅姜,但是IE8/9則比較特殊:IE8它使用的是ES3闪朱,而IE9則對ES5部分支持。這種情況下還需要ES5的polyfill es5-shim支持了钻洒。

2奋姿、fetch默認(rèn)不攜帶cookie
若要fetch請求攜帶cookie信息,只需設(shè)置一下credentials選項即可航唆,例如fetch(url, {credentials: 'include'});

3胀蛮、fetch請求對某些錯誤http狀態(tài)不會reject
這主要是由fetch返回promise導(dǎo)致的院刁,因為fetch返回的promise在某些錯誤的http狀態(tài)下如400糯钙、500等不會reject,相反它會被resolve;只有網(wǎng)絡(luò)錯誤會導(dǎo)致請求不能完成時任岸,fetch 才會被 reject再榄;所以一般會對fetch請求做一層封裝,例如下面代碼所示:

4享潜、fetch不支持超時timeout處理
用過fetch的都知道困鸥,fetch不像大多數(shù)ajax庫那樣對請求設(shè)置超時timeout,它沒有有關(guān)請求超時的feature剑按,這一點比較蛋疼疾就。所以在fetch標(biāo)準(zhǔn)添加超時feature之前,都需要polyfill該特性艺蝴。

5猬腰、fetch不支持JSONP

13、JS怎么實現(xiàn)異步

1猜敢、回調(diào)函數(shù)(定時器姑荷、事件監(jiān)聽)
2、Promises對象 generator async/await
3缩擂、發(fā)布訂閱者模式

14鼠冕、異步整個執(zhí)行周期
image.png
15、JS為什么要區(qū)分微任務(wù)和宏任務(wù)
16胯盯、介紹下Promise懈费,內(nèi)部實現(xiàn)x3

是ES6標(biāo)準(zhǔn)的異步編程的一種解決方案,解決回調(diào)地獄

Promise 是異步編程的一種解決方案陨闹,比傳統(tǒng)的解決方案——回調(diào)函數(shù)和事件——更合理和更強(qiáng)大楞捂。它由社區(qū)最早提出和實現(xiàn),ES6 將其寫進(jìn)了語言標(biāo)準(zhǔn)趋厉,統(tǒng)一了用法寨闹,原生提供了Promise對象。所謂Promise君账,簡單說就是一個容器繁堡,里面保存著某個未來才會結(jié)束的事件(通常是一個異步操作)的結(jié)果。從語法上說乡数,Promise 是一個對象椭蹄,從它可以獲取異步操作的消息送爸。Promise 提供統(tǒng)一的 API糕篇,各種異步操作都可以用同樣的方法進(jìn)行處理。

17疟呐、手寫Promise實現(xiàn)x3

https://juejin.im/post/5d0da5c8e51d455ca0436271

18玖翅、介紹下Promise的用途和性質(zhì)

用途
是ES6標(biāo)準(zhǔn)的異步編程的一種解決方案翼馆,解決回調(diào)地獄

性質(zhì)
1割以,promise內(nèi)部分微任務(wù)和宏任務(wù)
2,promise本身是同步的应媚,但是他的成功的回調(diào).then方法里面是異步的
3严沥,promise的狀態(tài)是不可逆的
4,then return出去的值中姜,會被后面的then接收消玄,如果后面還有跟then的話,catch同理
4丢胚,promise不管返回什么值翩瓜,都會被包裝成一個promise對象,即使這個返回值是error
5携龟,then接收到的值奥溺,如果不是一個函數(shù),會穿透到后面的then
5骨宠,promise對象如果resolve或者reject的也是一個promise對象浮定,那么promise對象的狀態(tài)會由reslove或者reject的promise對象的狀態(tài)決定。

19层亿、介紹Promise桦卒,異常捕獲

①第一種單獨對 .then() 中指定異常處理函數(shù)(第一種一般用在,希望捕獲異常然后不影響接下里Promise的執(zhí)行)我們只需要在 .then() 中添加兩個function就好了匿又,第二個是用來處理失敗的情況方灾。
②第二種使用.catch來實現(xiàn)全部捕獲(第二種一般用在,當(dāng)一個Promise發(fā)生了異常碌更,剩下的Promise都不在執(zhí)行)

一般總是建議裕偿,Promise 對象后面要跟catch方法,這樣可以處理 Promise 內(nèi)部發(fā)生的錯誤痛单。catch方法返回的還是一個 Promise 對象嘿棘,因此后面還可以接著調(diào)用then方法。

代碼因為沒有報錯旭绒,會跳過了catch方法鸟妙,直接執(zhí)行后面的then方法。此時挥吵,要是then方法里面報錯重父,就與前面的catch無關(guān)了『鲂伲可以用第二個catch方法用來捕獲前一個catch或者then方法拋出的錯誤房午。

Promise.prototype.catch方法是.then(null, rejection)或.then(undefined, rejection)的別名,用于指定發(fā)生錯誤時的回調(diào)函數(shù)丹允。

getJSON('/posts.json').then(function(posts) {
  // ...
}).catch(function(error) {
  // 處理 getJSON 和 前一個回調(diào)函數(shù)運行時發(fā)生的錯誤
  console.log('發(fā)生錯誤郭厌!', error);
});

上面代碼中嗦锐,getJSON方法返回一個 Promise 對象,如果該對象狀態(tài)變?yōu)閞esolved沪曙,則會調(diào)用then方法指定的回調(diào)函數(shù);如果異步操作拋出錯誤萎羔,狀態(tài)就會變?yōu)閞ejected液走,就會調(diào)用catch方法指定的回調(diào)函數(shù),處理這個錯誤贾陷。另外缘眶,then方法指定的回調(diào)函數(shù),如果運行中拋出錯誤髓废,也會被catch方法捕獲巷懈。

p.then((val) => console.log('fulfilled:', val))
  .catch((err) => console.log('rejected', err));

// 等同于
p.then((val) => console.log('fulfilled:', val))
  .then(null, (err) => console.log("rejected:", err));

如果 Promise 狀態(tài)已經(jīng)變成resolved,再拋出錯誤是無效的慌洪。

const promise = new Promise(function(resolve, reject) {
  resolve('ok');
  throw new Error('test');
});
promise
  .then(function(value) { console.log(value) })
  .catch(function(error) { console.log(error) });
// ok

上面代碼中顶燕,Promise 在resolve語句后面,再拋出錯誤冈爹,不會被捕獲涌攻,等于沒有拋出。因為 Promise 的狀態(tài)一旦改變频伤,就永久保持該狀態(tài)恳谎,不會再變了。Promise 對象的錯誤具有“冒泡”性質(zhì)憋肖,會一直向后傳遞因痛,直到被捕獲為止。也就是說岸更,錯誤總是會被下一個catch語句捕獲鸵膏。

getJSON('/post/1.json').then(function(post) {
  return getJSON(post.commentURL);
}).then(function(comments) {
  // some code
}).catch(function(error) {
  // 處理前面三個Promise產(chǎn)生的錯誤
});
20、如何實現(xiàn) Promise.finally ?

finally方法用于指定不管 Promise 對象最后狀態(tài)如何怎炊,都會執(zhí)行的操作较性。該方法是 ES2018 引入標(biāo)準(zhǔn)的。

promise
.then(result => {···})
.catch(error => {···})
.finally(() => {···});

上面代碼中结胀,不管promise最后的狀態(tài)赞咙,在執(zhí)行完then或catch指定的回調(diào)函數(shù)以后,都會執(zhí)行finally方法指定的回調(diào)函數(shù)糟港。finally本質(zhì)上是then方法的特例攀操。

promise
.finally(() => {
  // 語句
});

// 等同于
promise
.then(
  result => {
    // 語句
    return result;
  },
  error => {
    // 語句
    throw error;
  }
);

實現(xiàn)

Promise.prototype.finally = function (callback) {
  let P = this.constructor;
  return this.then(
    value  => P.resolve(callback()).then(() => value),
    reason => P.resolve(callback()).then(() => { throw reason })
  );
};
21、實現(xiàn)promise.all和原理x2

Promise.all()方法用于將多個 Promise 實例秸抚,包裝成一個新的 Promise 實例速和。

const p = Promise.all([p1, p2, p3]);
上面代碼中歹垫,Promise.all()方法接受一個數(shù)組作為參數(shù),p1颠放、p2排惨、p3都是 Promise 實例,如果不是碰凶,就會先調(diào)用下面講到的Promise.resolve方法暮芭,將參數(shù)轉(zhuǎn)為 Promise 實例,再進(jìn)一步處理欲低。另外辕宏,Promise.all()方法的參數(shù)可以不是數(shù)組,但必須具有 Iterator 接口砾莱,且返回的每個成員都是 Promise 實例瑞筐。

p的狀態(tài)由p1、p2腊瑟、p3決定聚假,分成兩種情況。

(1)只有p1闰非、p2魔策、p3的狀態(tài)都變成fulfilled,p的狀態(tài)才會變成fulfilled河胎,此時p1闯袒、p2、p3的返回值組成一個數(shù)組游岳,傳遞給p的回調(diào)函數(shù)政敢。

(2)只要p1、p2胚迫、p3之中有一個被rejected喷户,p的狀態(tài)就變成rejected,此時第一個被reject的實例的返回值访锻,會傳遞給p的回調(diào)函數(shù)褪尝。

下面是一個具體的例子。

// 生成一個Promise對象的數(shù)組
const promises = [2, 3, 5, 7, 11, 13].map(function (id) {
  return getJSON('/post/' + id + ".json");
});

Promise.all(promises).then(function (posts) {
  // ...
}).catch(function(reason){
  // ...
});

上面代碼中期犬,promises是包含 6 個 Promise 實例的數(shù)組河哑,只有這 6 個實例的狀態(tài)都變成fulfilled,或者其中有一個變?yōu)閞ejected龟虎,才會調(diào)用Promise.all方法后面的回調(diào)函數(shù)璃谨。

實現(xiàn)

function isPromise(obj) {
    return !!obj && (typeof obj === 'object' || typeof obj === 'function') && typeof obj.then === 'function';  
}

const myPromiseAll = (arr)=>{
    let result = [];
    return new Promise((resolve,reject)=>{
        for(let i = 0;i < arr.length;i++){
            if(isPromise(arr[i])){
                arr[i].then((data)=>{
                    result[i] = data;
                    if(result.length === arr.length){
                        resolve(result)
                    }
                },reject)
            }else{
                result[i] = arr[i];
            }
        }    
    })
}
22、實現(xiàn)promise.retry
Promise.retry = function(getData, times, delay) {
    return new Promise((resolve, reject) => {
        function attemp() {
            getData().then((data) => {
                resolve(data)
            }).catch((err) => {
                if (times === 0) {
                    reject(err)
                } else {
                    times--
                    setTimeout(attemp, delay)
                }
            })
        }
        attemp()
    })
}
23、介紹Promise和then佳吞,promise里面和then里面執(zhí)行有什么區(qū)別x2

當(dāng)我們在構(gòu)造Promise的時候拱雏,構(gòu)造函數(shù)內(nèi)部的代碼是立即執(zhí)行的,then是異步的

new Promise((resolve, reject) => {
resolve('success')
console.log('new Promise')
})
console.log('finifsh')
// new Promise -> finifsh

Promise實現(xiàn)了鏈?zhǔn)秸{(diào)用,也就是說每次調(diào)用then之后返回的都是一個Promise底扳,并且是一個全新的Promise铸抑,原因也是因為狀態(tài)不可變。如果你在then中 使用了return衷模,那么return的值會被Promise.resolve()包裝

Promise.resolve(1)
  .then(res => {
    console.log(res) // => 1
    return 2 // 包裝成 Promise.resolve(2)
  })
  .then(res => {
    console.log(res) // => 2
  })
24鹊汛、Promise 和 async/await 和 callback 、Generator的區(qū)別x3

Promise
promise比較簡單算芯,也是最常用的,主要就是將原來的用回調(diào)函數(shù)的異步編程方法轉(zhuǎn)成用relsove和reject觸發(fā)事件凳宙, 用then和catch捕獲成功或者失敗的狀態(tài)執(zhí)行相應(yīng)代碼的異步編程的方法,由下面代碼可以看出 promise將多個回調(diào)函數(shù)嵌套的回調(diào)地獄 熙揍,變成了鏈?zhǔn)降膶懛?,可讀性更高寫法也更清晰

//回調(diào)寫法
function fun1(value,callback) {
    value++
    setTimeout(function() {
            value++
        setTimeout(function(){
                value++
           setTimeout(function(){
                console.log(value)
           }氏涩,2000)届囚;
        },2000)是尖;
    意系,2000);
}
fun1() // 4

//Promise寫法
function fun1(value) {
    retrun  new Promise((resolve,reject)=> {
        setTimeout(function(callback){
            resolve(value++)
        }饺汹,2000)蛔添;
    }) 
}

fun1(0).then((value)=> {
    return  new Promise((resolve,reject)=> {
        setTimeout(function(callback){
            resolve(value++)
        },2000)兜辞;
}).then((value)=> {
    return  new Promise((resolve,reject)=> {
        setTimeout(function(callback){
            resolve(value++)
        }迎瞧,2000);
}).then(value)=>{
    console.log(value) 
}    // 4

Generator函數(shù)
Generator函數(shù)是將函數(shù)分步驟阻塞 逸吵,只有主動調(diào)用next() 才能進(jìn)行下一步 凶硅,因為asyns函數(shù)相當(dāng)于Generator函數(shù)的語法糖,做出了優(yōu)化扫皱,所以這里對Generator函數(shù)不做贅述足绅,而且一般用到異步編程的時候一般也只用async和promise。所以這里就省略了,這里改一下韩脑,因為dva中異步處理的實現(xiàn)就是Generator函數(shù)氢妈,所以還是挺有用的,當(dāng)然dva中自己帶狀態(tài)機(jī)使函數(shù)自動運行下去段多。

async函數(shù)
簡單的說async函數(shù)就相當(dāng)于自執(zhí)行的Generator函數(shù)允懂,相當(dāng)于自帶一個狀態(tài)機(jī),在await的部分等待返回衩匣, 返回后自動執(zhí)行下一步蕾总。而且相較于Promise,async的優(yōu)越性就是把每次異步返回的結(jié)果從then中拿到最外層的方法中粥航,不需要鏈?zhǔn)秸{(diào)用,只要用同步的寫法就可以了生百。更加直觀而且递雀,更適合處理并發(fā)調(diào)用的問題。但是async必須以一個Promise對象開始 蚀浆,所以async通常是和Promise結(jié)合使用的

//async函數(shù)寫法
function fun1(value) {
    retrun  new Promise((resolve,reject)=> {
        setTimeout(function(callback){
            resolve(value++)
        }缀程,2000);
    }) 
}

async function asy() {
let v = 0
    v = await fun1(v)
    v = await fun1(v)
    v = await fun1(v)
    console.log(v)
}  
asy() //4

從上面代碼來看await函數(shù)的寫法確實簡潔了很多市俊,而且異步的順序也非常清晰杨凑。總的來說摆昧,async和generator函數(shù)主要就是為了解決異步的并發(fā)調(diào)用使用的 撩满,直接將參數(shù)從then里取出來,相比promise的鏈?zhǔn)秸{(diào)用绅你,傳參更加方便伺帘,異步順序更加清晰

另外: 我覺得這題主要是考察這三者在事件循環(huán)中的區(qū)別,事件循環(huán)中分為宏任務(wù)隊列和微任務(wù)隊列忌锯。 其中setTimeout的回調(diào)函數(shù)放到宏任務(wù)隊列里伪嫁,等到執(zhí)行棧清空以后執(zhí)行; promise.then里的回調(diào)函數(shù)會放到相應(yīng)宏任務(wù)的微任務(wù)隊列里偶垮,等宏任務(wù)里面的同步代碼執(zhí)行完再執(zhí)行张咳;async函數(shù)表示函數(shù)里面可能會有異步方法,await后面跟一個表達(dá)式似舵,async方法執(zhí)行時晶伦,遇到await會立即執(zhí)行表達(dá)式,然后把表達(dá)式后面的代碼放到微任務(wù)隊列里啄枕,讓出執(zhí)行棧讓同步代碼先執(zhí)行婚陪。

25、Promise有沒有解決異步的問題(promise鏈?zhǔn)钦嬲龔?qiáng)大的地方)

是ES6標(biāo)準(zhǔn)的異步編程的一種解決方案频祝,promise主要是為了解決嵌套回調(diào)的問題(回調(diào)地獄)泌参,使代碼更加簡潔,promise將嵌套的回調(diào)函數(shù)改成.then()的鏈?zhǔn)绞褂?/p>

首先通過new Promise(function)創(chuàng)建一個promise對象常空,接收一個函數(shù)參數(shù)沽一,并且在函數(shù)中傳入resolve以及reject兩個參數(shù);

then() 接收兩個函數(shù)漓糙,分別是對promise的resolve及reject狀態(tài)處理的函數(shù)铣缠,并且處理結(jié)束之后返回promise對象

all() 接收一個函數(shù)數(shù)組,進(jìn)行并發(fā)操作,并將每個函數(shù)的結(jié)果以數(shù)組的形式返回

race()接收函數(shù)數(shù)組蝗蛙,函數(shù)先執(zhí)行完成之后先進(jìn)入下一個回調(diào)函數(shù)中

catch() 當(dāng)then中出現(xiàn)錯誤時不會中止整個函數(shù)蝇庭,catch能夠獲取到錯誤并進(jìn)行提示

26、promise 有幾種狀態(tài), Promise 有什么特色和優(yōu)缺點 x4

等待中(pending) 完成了 (resolved) 拒絕了(rejected)

Promise對象有以下兩個特點捡硅。

(1)對象的狀態(tài)不受外界影響
Promise對象代表一個異步操作哮内,有三種狀態(tài):pending(進(jìn)行中)、fulfilled(已成功)和rejected(已失斪尘隆)北发。只有異步操作的結(jié)果,可以決定當(dāng)前是哪一種狀態(tài)喷屋,任何其他操作都無法改變這個狀態(tài)琳拨。這也是Promise這個名字的由來,它的英語意思就是“承諾”屯曹,表示其他手段無法改變狱庇。

(2)一旦狀態(tài)改變,就不會再變是牢,任何時候都可以得到這個結(jié)果
Promise對象的狀態(tài)改變僵井,只有兩種可能:從pending變?yōu)?code>fulfilled和從pending變?yōu)?code>rejected陕截。只要這兩種情況發(fā)生驳棱,狀態(tài)就凝固了,不會再變了农曲,會一直保持這個結(jié)果社搅,這時就稱為 resolved(已定型)。如果改變已經(jīng)發(fā)生了乳规,你再對Promise對象添加回調(diào)函數(shù)形葬,也會立即得到這個結(jié)果。這與事件(Event)完全不同暮的,事件的特點是笙以,如果你錯過了它,再去監(jiān)聽冻辩,是得不到結(jié)果的猖腕。

注意,為了行文方便恨闪,本章后面的resolved統(tǒng)一只指fulfilled狀態(tài)倘感,不包含rejected狀態(tài)。

有了Promise對象咙咽,就可以將異步操作以同步操作的流程表達(dá)出來老玛,避免了層層嵌套的回調(diào)函數(shù)。此外,Promise對象提供統(tǒng)一的接口蜡豹,使得控制異步操作更加容易麸粮。

Promise也有一些缺點。
①無法取消Promise余素,一旦新建它就會立即執(zhí)行豹休,無法中途取消。
②如果不設(shè)置回調(diào)函數(shù)桨吊,Promise內(nèi)部拋出的錯誤威根,不會反應(yīng)到外部。
③當(dāng)處于pending狀態(tài)時视乐,無法得知目前進(jìn)展到哪一個階段(剛剛開始還是即將完成)洛搀。

如果某些事件不斷地反復(fù)發(fā)生,一般來說佑淀,使用 Stream 模式是比部署Promise更好的選擇

27留美、Promise構(gòu)造函數(shù)是同步還是異步執(zhí)行,then呢 ?promise如何實現(xiàn)then處理 ? x3

Promise構(gòu)造函數(shù)是同步伸刃,then是異步

Promise實例具有then方法谎砾,也就是說then方法時定義在原型對象上的。它的作用是為Promise實例添加狀態(tài)改變時的回調(diào)函數(shù)捧颅。前面說過景图,then方法的第一個參數(shù)是resolved狀態(tài)的回調(diào)函數(shù),第二個參數(shù)是rejected狀態(tài)的回調(diào)函數(shù)(可選)碉哑。then方法返回的是一個新的Promise實例(注意挚币,不是原來那個Promise實例)因此可以采用鏈?zhǔn)綄懛?/code>,即then方法后面再調(diào)用另一個then方法扣典。采用鏈?zhǔn)降膖hen可以指定一組按照次序調(diào)用的回調(diào)函數(shù)妆毕。這時,前一個回調(diào)函數(shù)可能返回一個還是Promise對象(即有異步操作)贮尖,這時候一個回調(diào)函數(shù)就會等該Promise對象的狀態(tài)發(fā)生變化笛粘,才會被調(diào)用。

getJSON("/post/1.json").then(function(post) {
  return getJSON(post.commentURL);
}).then(function (comments) {
  console.log("resolved: ", comments);
}, function (err){
  console.log("rejected: ", err);
});

上面代碼中湿硝,第一個then方法指定的回調(diào)函數(shù)薪前,返回的是另一個Promise對象。這時图柏,第二個then方法指定的回調(diào)函數(shù)序六,就會等待這個新的Promise對象狀態(tài)發(fā)生變化。如果變?yōu)閞esolved蚤吹,就調(diào)用第一個回調(diào)函數(shù)例诀,如果狀態(tài)變?yōu)閞ejected随抠,就調(diào)用第二個回調(diào)函數(shù)。

如果采用箭頭函數(shù)繁涂,上面的代碼可以寫得更簡潔拱她。

getJSON("/post/1.json").then(
  post => getJSON(post.commentURL)
).then(
  comments => console.log("resolved: ", comments),
  err => console.log("rejected: ", err)
);

實現(xiàn)then處理

// then方法接收兩個參數(shù),fn1扔罪,fn2秉沼,分別為Promise成功或失敗后的回調(diào)
Promise.prototype.then = function(fn1, fn2) {
  var self = this
  var promise2

  // 首先對入?yún)?fn1, fn2做判斷
  fn1 = typeof fn1 === 'function' ? fn1 : function(v) {}
  fn2 = typeof fn2 === 'function' ? fn2 : function(r) {}

  if (self.status === 'resolved') {
    return promise2 = new Promise(function(resolve, reject) {
        //todo
    })
  }

  if (self.status === 'rejected') {
    return promise2 = new Promise(function(resolve, reject) {
       //todo
    })
  }

  if (self.status === 'pending') {
    return promise2 = new Promise(function(resolve, reject) {
       // todo
    })
  }
}
28、Promise和setTimeout的區(qū)別(Event Loop)x3

Promise構(gòu)造函數(shù)中是立即執(zhí)行(同步任務(wù))矿酵,then函數(shù)分發(fā)到微任務(wù)Event Queue(異步任務(wù))唬复,setTimeout是分發(fā)到宏任務(wù)中

29、將一個同步callback包裝成promise形式

本文要介紹的是如何將 callback 轉(zhuǎn)換成 Promise全肮,主要是寫了一個具體的例子敞咧。首先請大家瀏覽一下這篇文章:
如何把 Callback 接口包裝成 Promise 接口

接下來我遇到的問題是,如何把像 jquery 方式的 ajax 請求改成 promise 呢辜腺?因為 jquery 的 ajax 有兩個回調(diào)函數(shù):success 和 error 用來接收成功的請求和錯誤休建。那么,我們就可以根據(jù)上文的思路评疗,在 success 和 error 中處理 promise 的消息就好了测砂。于是就有了以下例子:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script>
<script>
// 將 jquery 的 ajax 方法封裝為 Promise 方法
function post (url, params) {
  return new Promise(
    (resolve, reject) => {
      jQuery.ajax({
        url,
        data: {...params},
        type: "post",
        success: function (res) {
          resolve(res)
        },
        error: function (res) {
          reject(res)
        }
      }) 
    }
  )
}

// 異步請求,使用 then 和 catch
function asyncPost () {
  console.log('==== 異步請求 start =====')
  post(
    'http://removeUrl',
    {
      foo: 'qwwerwer'
    }
  ).then(res => {
    console.log(res)
  }).catch(err => {
    console.log(err)
  })
  console.log('==== 異步請求 end =====')
}

// 同步請求百匆,使用 async 和 await
async function syncPost() {
  try {
    console.log('==== 同步請求 start =====')
    let res = await post(
      'http://removeUrl',
      {
        foo: 'qwwerwer'
      }
    )
    console.log(res)
    console.log('==== 同步請求 end =====')
  } catch (e) {
    console.log(e)
  }
}
</script>
</head>
<body>
  <button onclick="promisePost()">promisePost提交</button>
  <button onclick="asyncPost()">asyncPost提交</button>
</body>
</html>
30砌些、設(shè)計并實現(xiàn) Promise.race()
Promise._race = promises => new Promise((resolve, reject) => {
    promises.forEach(promise => {
        promise.then(resolve, reject)
    })
})
31、使用Async會注意哪些東西

特點

  1. await只能放到async函數(shù)中
  2. 相比genrator語義化更強(qiáng)
  3. await后面可以是promise對象胧华,也可以數(shù)字寄症、字符串宙彪、布爾
  4. async函數(shù)總是返回是一個promise對象
  5. 只要await語句后面Promise狀態(tài)變成 reject, 那么整個async函數(shù)會中斷執(zhí)行
    6.async函數(shù)和普通函數(shù)一樣按順序執(zhí)行矩动,同時,在執(zhí)行到await語句時释漆,返回一個Promise對象

注意
1)await 命令后面的Promise對象悲没,運行結(jié)果可能是 rejected,此時等同于 async 函數(shù)返回的 Promise 對象被reject男图。因此需要加上錯誤處理示姿,可以給每個 await 后的 Promise 增加 catch 方法;也可以將 await 的代碼放在 try…catch 中逊笆。
2)多個await命令后面的異步操作栈戳,如果不存在繼發(fā)關(guān)系,最好讓它們同時觸發(fā)难裆,代碼如下

//下面兩種寫法都可以同時觸發(fā)
//法一
async function f1() {
    await Promise.all([
        new Promise((resolve) => {
            setTimeout(resolve, 600);
        }),
        new Promise((resolve) => {
            setTimeout(resolve, 600);
        })
    ])
}
//法二
async function f2() {
    let fn1 = new Promise((resolve) => {
            setTimeout(resolve, 800);
        });
    
    let fn2 = new Promise((resolve) => {
            setTimeout(resolve, 800);
        })
    await fn1;
    await fn2;
}

3)await命令只能用在async函數(shù)之中子檀,如果用在普通函數(shù)镊掖,會報錯
4)async 函數(shù)可以保留運行堆棧
實例代碼:

/
* 函數(shù)a內(nèi)部運行了一個異步任務(wù)b()。當(dāng)b()運行的時候褂痰,函數(shù)a()不會中斷亩进,而是繼續(xù)執(zhí)行。
* 等到b()運行結(jié)束缩歪,可能a()早就* 運行結(jié)束了归薛,b()所在的上下文環(huán)境已經(jīng)消失了。
* 如果b()或c()報錯匪蝙,錯誤堆棧將不包括a()主籍。
*/
function b() {
    return new Promise((resolve, reject) => {
        setTimeout(resolve, 200)
    });
}
function c() {
    throw Error(10);
}
const a = () => {
    b().then(() => c());
};
a();
/**
* 改成async函數(shù)
*/
const m = async () => {
    await b();
    c();
};
m();
32、Async里面有多個await請求逛球,可以怎么優(yōu)化(請求是否有依賴)
33崇猫、對async、await的理解需忿,內(nèi)部原理以及實現(xiàn)

1)async 函數(shù)是 Generator 函數(shù)的語法糖诅炉,使用 關(guān)鍵字 async 來表示,在函數(shù)內(nèi)部使用 await 來表示異步
2)ES7 提出的async 函數(shù)屋厘,終于讓 JavaScript 對于異步操作有了終極解決方案
3)async 作為一個關(guān)鍵字放到函數(shù)的前面涕烧,用于表示函數(shù)是一個異步函數(shù),該函數(shù)的執(zhí)行不會阻塞后面代碼的執(zhí)行
4)await是等待汗洒,只能放到async函數(shù)里面议纯,在后面放一個返回promise對象的表達(dá)式
5)async和await是為了解決大量復(fù)雜不易讀的Promise異步的問題

async 函數(shù)的實現(xiàn)原理,就是將 Generator 函數(shù)和自動執(zhí)行器溢谤,包裝在一個函數(shù)里瞻凤。

1)內(nèi)置執(zhí)行器,Generator 函數(shù)的執(zhí)行必須依靠執(zhí)行器世杀,而 Aysnc 函數(shù)自帶執(zhí)行器阀参,調(diào)用方式跟普通函數(shù)的調(diào)用一樣
2)更好的語義,async 和 await 相較于 * 和 yield 更加語義化瞻坝,async 函數(shù)就是將 Generator 函數(shù)的星號(*)替換成 async蛛壳,將 yield 替換成await
3)更廣的適用性,co 模塊約定所刀,yield 命令后面只能是 Thunk 函數(shù)或 Promise對象衙荐,而 async 函數(shù)的 await 命令后面則可以是 Promise 或者 原始類型的值(Number,string浮创,boolean忧吟,但這時等同于同步操作)
4)返回值是 Promise,async 函數(shù)返回值是 Promise 對象斩披,比 Generator 函數(shù)返回的 Iterator 對象方便溜族,可以直接使用 then() 方法進(jìn)行調(diào)用
5)async方式胸嘴,流程清晰,直觀斩祭、語義明顯劣像,操作異步流程就如同操作同步流程, async 函數(shù)自帶執(zhí)行器摧玫,執(zhí)行的時候無需手動加載耳奕。對于Promise的方式,如果處理流程復(fù)雜诬像,整段代碼將會充滿then屋群,不然很好的表示流程。對于Generator 方式坏挠,函數(shù)的執(zhí)行需要依靠執(zhí)行器芍躏,每次都需要通過 g.next() 的方式去執(zhí)行

實現(xiàn)

function my_co(it) {
    return new Promise((resolve, reject) => {
        function next(data) {
            try {
                var { value, done } = it.next(data);
            }catch(e){
                return reject(e);
            }
            if (!done) { 
                //done為true,表示迭代完成
                //value 不一定是 Promise,可能是一個普通值降狠。使用 Promise.resolve 進(jìn)行包裝对竣。
                Promise.resolve(value).then(val => {
                    next(val);
                }, reject);
            } else {
                resolve(value);
            }
        }
        next(); //執(zhí)行一次next
    });
}
function* test() {
    yield new Promise((resolve, reject) => {
        setTimeout(resolve, 100);
    });
    yield new Promise((resolve, reject) => {
        // throw Error(1);
        resolve(10)
    });
    yield 10;
    return 1000;
}

my_co(test()).then(data => {
    console.log(data); //輸出1000
}).catch((err) => {
    console.log('err: ', err);
});

34、Promise和Async處理失敗的時候有什么區(qū)別

Async/Await讓try/catch可以同時處理同步和異步錯誤榜配。在下面的promise示例中否纬,try/catch不能處理JSON.parse的錯誤,因為它在Promise中蛋褥。我們需要使用.catch临燃,這樣錯誤處理代碼非常冗余。并且烙心,在我們的實際生產(chǎn)代碼會更加復(fù)雜膜廊。

const makeRequest = () => {
  try {
    getJSON()
      .then(result => {
        // JSON.parse可能會出錯
        const data = JSON.parse(result)
        console.log(data)
      })
      // 取消注釋,處理異步代碼的錯誤
      // .catch((err) => {
      //   console.log(err)
      // })
  } catch (err) {
    console.log(err)
  }
}

使用aync/await的話淫茵,catch能處理JSON.parse錯誤:

const makeRequest = async () => {
  try {
    // this parse may fail
    const data = JSON.parse(await getJSON())
    console.log(data)
  } catch (err) {
    console.log(err)
  }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末爪瓜,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子痘昌,更是在濱河造成了極大的恐慌钥勋,老刑警劉巖炬转,帶你破解...
    沈念sama閱讀 218,122評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件辆苔,死亡現(xiàn)場離奇詭異,居然都是意外死亡扼劈,警方通過查閱死者的電腦和手機(jī)驻啤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來荐吵,“玉大人骑冗,你說我怎么就攤上這事赊瞬。” “怎么了贼涩?”我有些...
    開封第一講書人閱讀 164,491評論 0 354
  • 文/不壞的土叔 我叫張陵巧涧,是天一觀的道長。 經(jīng)常有香客問我遥倦,道長谤绳,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,636評論 1 293
  • 正文 為了忘掉前任袒哥,我火速辦了婚禮缩筛,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘堡称。我一直安慰自己瞎抛,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,676評論 6 392
  • 文/花漫 我一把揭開白布却紧。 她就那樣靜靜地躺著桐臊,像睡著了一般。 火紅的嫁衣襯著肌膚如雪晓殊。 梳的紋絲不亂的頭發(fā)上豪硅,一...
    開封第一講書人閱讀 51,541評論 1 305
  • 那天,我揣著相機(jī)與錄音挺物,去河邊找鬼懒浮。 笑死,一個胖子當(dāng)著我的面吹牛识藤,可吹牛的內(nèi)容都是我干的砚著。 我是一名探鬼主播,決...
    沈念sama閱讀 40,292評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼痴昧,長吁一口氣:“原來是場噩夢啊……” “哼稽穆!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起赶撰,我...
    開封第一講書人閱讀 39,211評論 0 276
  • 序言:老撾萬榮一對情侶失蹤舌镶,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后豪娜,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體餐胀,經(jīng)...
    沈念sama閱讀 45,655評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,846評論 3 336
  • 正文 我和宋清朗相戀三年瘤载,在試婚紗的時候發(fā)現(xiàn)自己被綠了否灾。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,965評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡鸣奔,死狀恐怖墨技,靈堂內(nèi)的尸體忽然破棺而出惩阶,到底是詐尸還是另有隱情,我是刑警寧澤扣汪,帶...
    沈念sama閱讀 35,684評論 5 347
  • 正文 年R本政府宣布断楷,位于F島的核電站,受9級特大地震影響崭别,放射性物質(zhì)發(fā)生泄漏脐嫂。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,295評論 3 329
  • 文/蒙蒙 一紊遵、第九天 我趴在偏房一處隱蔽的房頂上張望账千。 院中可真熱鬧,春花似錦暗膜、人聲如沸匀奏。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽娃善。三九已至,卻和暖如春瑞佩,著一層夾襖步出監(jiān)牢的瞬間聚磺,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評論 1 269
  • 我被黑心中介騙來泰國打工炬丸, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留瘫寝,地道東北人。 一個月前我還...
    沈念sama閱讀 48,126評論 3 370
  • 正文 我出身青樓稠炬,卻偏偏與公主長得像焕阿,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子首启,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,914評論 2 355

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

  • 弄懂js異步 講異步之前暮屡,我們必須掌握一個基礎(chǔ)知識-event-loop。 我們知道JavaScript的一大特點...
    DCbryant閱讀 2,711評論 0 5
  • async 函數(shù) ES2017 標(biāo)準(zhǔn)引入了 async 函數(shù)毅桃,使得異步操作變得更加方便褒纲。async 函數(shù)是什么?一...
    _羊羽_閱讀 2,105評論 0 1
  • 面試題一:https://github.com/jimuyouyou/node-interview-questio...
    R_X閱讀 1,623評論 0 5
  • JS為什么是單線程的? 最初設(shè)計JS是用來在瀏覽器驗證表單操控DOM元素的是一門腳本語言钥飞,如果js是多線程的那么兩...
    船長___閱讀 2,198評論 1 15
  • 上篇 中篇 下篇 1 什么是異步編程 1.1 阻塞 程序未得到所需計算資源時被掛起的狀態(tài)莺掠。 程序在等待某個操作完成...
    秦時明星閱讀 1,002評論 0 3