本文是 ES6
系列的第三篇,能夠在 這裏 查看 往期全部內容git
本文的 答案
不必定是最優解釋,若是你有更好的想法或更優雅的寫法,歡迎留言討論es6
若是文章中有出現紕漏、錯誤之處,還請看到的小夥伴多多指教,先行謝過github
如下web
下面的代碼輸出什麼面試
let promise = new Promise((resolve, reject) => { console.log(1) setTimeout(() => { resolve(2) console.log(3) }, 2000); reject('error') }) promise .then(res => { console.log(5) }) .catch(err => { console.log(err) })
答案ajax
1 error 3數組
要點解析:promise
promise
建立以後會當即執行reject
與 resolve
只會執行其中的一個推薦閱讀 Js 執行機制微信
下面代碼輸出什麼異步
const first = () => (new Promise((resolve,reject)=>{ console.log(1); let p = new Promise((resolve, reject)=>{ console.log(2); setTimeout(()=>{ console.log(3); resolve(4); },0) resolve(5); }); resolve(6); p.then((arg)=>{ console.log(arg); }); })); first().then((arg)=>{ console.log(arg); }); console.log(7);
答案
1 2 7 5 6 3
一樣是 promise
結合 js
執行機制的問題
promise
建立當即執行,依次輸出 1 2
7
p.then
以及 first.then
加入微任務執行隊列,因此依次輸出 5 6
setTimeout
, 輸出 3
下面的代碼輸出什麼
Promise.resolve(1) .then(2) .then(Promise.resolve(3)) .then(console.log)
答案
1
then
方法的對象,則 Promise.resolve
方法返回一個新的 Promise
對象,狀態爲 resolved
then
方法接受的參數是函數,而若是傳遞的並不是是一個函數,就會致使前一個 Promise
的結果穿透到下面爲何建議在 promise 最後調用 catch 方法
答案
首先,來看一個例子
Promise.resolve().then(res => { throw new Error('error') }, err => { console.log(err) }).then(res => { console.log(1) })
上面的代碼中,咱們在 then
函數中拋出一個錯誤,想使用 then
中的第二個參數來捕獲這個錯誤。很顯然,錯誤在 Promise
函數體外拋出,冒泡到了最外層,成了未捕獲的錯誤,由於這裏捕獲的老是 以前的 Promise 產生的錯誤
因此,通常老是建議,Promise
對象後面要跟 catch
方法,這樣能夠處理 Promise
內部發生的錯誤
只是咱們須要注意的是 catch
方法也會返回一個新的 Promise
對象,能夠繼續使用 Promise
的方法,一樣也意味着 catch
方法中也可能產生錯誤
實現 mergePromise 函數,把傳進去的數組按順序前後執行,而且把返回的數據前後放到數組 data 中
const timeout = ms => new Promise((resolve, reject) => { setTimeout(() => { resolve(); }, ms); }); const ajax1 = () => timeout(2000).then(() => { console.log('1'); return 1; }); const ajax2 = () => timeout(1000).then(() => { console.log('2'); return 2; }); const ajax3 = () => timeout(2000).then(() => { console.log('3'); return 3; }); const mergePromise = ajaxArray => { // 在這裏實現你的代碼 }; mergePromise([ajax1, ajax2, ajax3]).then(data => { console.log('done'); console.log(data); // data 爲 [1, 2, 3] }); // 要求分別輸出 // 1 // 2 // 3 // done // [1, 2, 3]
答案
這個問題主要考察的就是咱們使用 Promise
對異步操做的控制
const mergePromise = ajaxArray => { // 保存數組在函數執行以後的結果 let data = [] // 建立一個 Promise 對象控制異步流程 let p = Promise.resolve() // 遍歷數組按次序執行數組中的每一項 // 將數組中每一項的執行結果保存起來到一個新數組 ajaxArray.forEach(item => { p = p.then(item).then(res => { data.push(res) return data }) }) // 最終獲得的結果:返回一個新的 Promise 對象 // return 的結果做爲參數傳遞到下次調用的 then 方法中 return p }
下面的代碼輸出什麼
function* foo(x) { var y = 2 * (yield (x + 1)); var z = yield (y / 3); return (x + y + z); } let b = foo(5); b.next() b.next(15) b.return('tadpole') b.next(12)
答案
// {value: 6, done: false} // {value: 10, done: false} // {value: 'tadpole', done: true} // {value: undefined, done: true}
next
的參數是上一次表達式的值return
方法,能夠返回給定的值,而且終結遍歷 Generator
函數下面的代碼輸出什麼
async function async1() { console.log("async1 start"); await async2(); console.log("async1 end"); return 'async return'; } async function async2() { console.log("async2"); } console.log("script start"); setTimeout(function() { console.log("setTimeout"); }, 0); async1().then(function (message) { console.log(message) }); new Promise(function(resolve) { console.log("promise1"); resolve(); }).then(function() { console.log("promise2"); }); console.log("script end")
答案
// 執行同步代碼,遇到 setTimeout 將其加入到宏任務隊列 script start // 執行 async1() async1 start // 遇到await 執行右側表達式後讓出線程,阻塞後面代碼 async2 // 執行 Promise 中的同步代碼 將 .then 推入到微任務隊列 promise1 // 執行同步代碼 script end // 繼續執行 await 後面的代碼 // 這裏須要注意 async 函數返回的是 Promise 對象 // 將 async1後面的 .then 加入到微任務隊列 async1 end // 執行前一輪添加到微任務隊列的代碼 promise2 // 後一輪微任務隊列的代碼 async return // 開始下一輪evenloop,執行宏任務隊列中的任務 setTimeout
使用不一樣的方式實現下面的需求
// 紅燈三秒亮一次,綠燈兩秒亮一次,黃燈一秒亮一次;如何讓三個燈不斷交替重複亮燈 // 使用 Callback/Promise/Genertor/async 分別實現 // 亮燈函數以下 function red(){ console.log('red'); } function green(){ console.log('green'); } function yellow(){ console.log('yellow'); }
答案
// callback function loop() { setTimeout(() => { red() setTimeout(() => { green() setTimeout(() => { yellow() loop() }, 1000) }, 2000) }, 3000) } loop() // Promise function fn(timer, cb) { return new Promise((resolve, reject) => { setTimeout(() => { cb() resolve() }, timer); }) } let promise = Promise.resolve() function loop() { promise.then(res => { return fn(3000, red) }).then(res => { return fn(2000, green) }).then(res => { return fn(1000, yellow) }).then(res => { loop() }) } // Generator function fn(timer, cb) { return new Promise((resolve, reject) => { setTimeout(() => { cb() resolve() }, timer) }) } function* gen() { yield fn(3000, red) yield fn(2000, green) yield fn(1000, yellow) } function loop(iterator, gen) { // 執行 Generator 函數 let result = iterator.next() if (result.done) { // 這裏須要從新開始執行 loop(gen(), gen) } else { result.value.then(res => { loop(iterator, gen) }) } } loop(gen(), gen) // Async function fn(timer, cb) { return new Promise((resolve, reject) => { setTimeout(() => { cb() resolve() }, timer) }) } async function loop() { while (true) { await fn(3000, red) await fn(2000, green) await fn(1000, yellow) } } loop()
以上就是本期 ES6
相關的全部內容,主要涉及的是 Promise
和 Generator
以及 Async
函數相關的內容,經過幾個常見的面試題以及需求考察對 ES6
相關知識的瞭解程度
留一個筆記,也但願對看到的小夥伴能有些許幫助
感興趣的小夥伴能夠 點擊這裏 ,也能夠掃描下方二維碼關注個人微信公衆號,查看往期更多內容,歡迎 star
關注