小編認識了一個去找實習的同學,聊了實習找得怎樣了,讓我印象最深刻的就是她講promise的面試題,她說一面結束後就知道涼涼了,並且要是有機會很想和麵試官說一句:面試官對不起!我終於會了Promise!至於為什麼會這麼說,大家看看面試題及同學的回答就知道這位同學有多難受了。
面試題
CSS 實現水平垂直居中
flex的屬性
CSS transition的實現效果和有哪些屬性
CSS 實現沿Y軸旋轉360度 (直接自爆了 CSS不行。。。。麻了)
好,那來點JS 基本資料型別有哪些 用什麼判斷
陣列怎麼判斷
引用型別和基本型別的區別
什麼是棧?什麼是堆?
手寫 翻轉字串
手寫 Sum(1,2,3)的累加(argument)(我以為是柯里化,面試官笑了一下,腦筋不要這麼死嘛)
箭頭函式和普通函式的區別(上題忘記了argument,面試官特意問這個問題提醒我,奈何基礎太差救不起來了。。。淚目)
陣列去重的方法
圖片懶載入
跨域產生的原因,同源策略是什麼
說說你瞭解的解決辦法(只說了JSONP和CORS)
Cookie、sessionStorage、localStorage的區別
get 和 post 的區別 (只說了傳參方式和功能不同,面試官問還有嗎 其他的不知道了。。。)
問了一下專案,react
對ES6的瞭解 (Promise果真逃不了。。。。)
let var const的區別
知道Promise嘛?聊聊對Promise的理解?(說了一下Promise物件代表一個非同步操作,有三種狀態,狀態轉變為單向。。。)
那它是為了解決什麼問題的?(emmm當非同步返回值又需要等待另一個非同步就會巢狀回撥,Promise可以解決這個回撥地獄問題)
那它是如何解決回撥地獄的?(Promise物件內部是同步的,內部得到內部值後進行呼叫。then的非同步操作,可以一直。then 。then 。。。)
好,你說可以一直。then 。then 。。。那它是如何實現一直。then 的?(emmm。。。 這個。then鏈式呼叫就是。。。額這個。。。)
Promise有哪些方法 all和race區別是什麼
具體說一下 。catch() 和 reject (。。。我人麻了。。。)
結束環節
問了面試官對CSS的理解(必須但非重要,前端的核心還是儘量一比一還原設計稿,只有寫好了頁面才能考慮互動)
如何學習(基礎是最重要的,CSS和JS要注重實踐,蓋房子最重要的還是地基,所有的框架原始碼,元件等都基於CSS和JS)
曾經是如何度過這個過程的(多做專案,在專案中學習理解每個細節,再次告誡我基礎的重要性)
Promise概述
Promise是ES6新增的引用型別,可以透過new來進行例項化物件。Promise內部包含著非同步的操作。
new Promise(fn)
Promise。resolve(fn)
這兩種方式都會返回一個 Promise 物件。
Promise 有三種狀態:
等待態(Pending)、執行態(Fulfilled)和拒絕態(Rejected)
,且Promise 必須為三種狀態之一隻有非同步操作的結果,可以決定當前是哪一種狀態,任何其他操作都無法改變這個狀態。
狀態只能由 Pending 變為 Fulfilled 或由 Pending 變為 Rejected
,且狀態改變之後不會再發生變化,會一直保持這個狀態。
Pending 變為 Fulfilled 會得到一個私有
value
,Pending 變為 Rejected會得到一個私有
reason
,當Promise達到了Fulfilled或Rejected時,執行的非同步程式碼會接收到這個value或reason。
知道了這些,我們可以得到下面的程式碼:
實現原理
class Promise { constructor() { this。state = ‘pending’ // 初始化 未完成狀態 // 成功的值 this。value = undefined; // 失敗的原因 this。reason = undefined; }}複製程式碼
基本用法
Promise狀態只能在內部進行操作,內部操作在Promise執行器函式執行。Promise必須接受一個函式作為引數,我們稱該函式為執行器函式,執行器函式又包含resolve和reject兩個引數,它們是兩個函式。
resolve : 將Promise物件的狀態從 Pending(進行中) 變為 Fulfilled(已成功)
reject : 將Promise物件的狀態從 Pending(進行中) 變為 Rejected(已失敗),並丟擲錯誤。
使用栗子
let p1 = new Promise((resolve,reject) => { resolve(value);})setTimeout(() => { console。log((p1)); // Promise {
實現原理
p1 resolve為成功,接收引數value,狀態改變為fulfilled,不可再次改變。
p2 reject為失敗,接收引數reason,狀態改變為rejected,不可再次改變。
如果executor執行器函式執行報錯,直接執行reject。
所以得到如下程式碼:
class Promise{ constructor(executor){ // 初始化state為等待態 this。state = ‘pending’; // 成功的值 this。value = undefined; // 失敗的原因 this。reason = undefined; let resolve = value => { console。log(value); if (this。state === ‘pending’) { // resolve呼叫後,state轉化為成功態 console。log(‘fulfilled 狀態被執行’); this。state = ‘fulfilled’; // 儲存成功的值 this。value = value; } }; let reject = reason => { console。log(reason); if (this。state === ‘pending’) { // reject呼叫後,state轉化為失敗態 console。log(‘rejected 狀態被執行’); this。state = ‘rejected’; // 儲存失敗的原因 this。reason = reason; } }; // 如果 執行器函式 執行報錯,直接執行reject try{ executor(resolve, reject); } catch (err) { reject(err); } } }複製程式碼
檢驗一下上述程式碼咯:
class Promise{。。。} // 上述程式碼new Promise((resolve, reject) => { console。log(0); setTimeout(() => { resolve(10) // 1 // reject(‘JS我不愛你了’) // 2 // 可能有錯誤 // throw new Error(‘是你的錯’) // 3 }, 1000)})複製程式碼
當執行程式碼1時輸出為
0
後一秒輸出
10
和
fulfilled 狀態被執行
;
當執行程式碼2時輸出為
0
後一秒輸出
我不愛你了
和
rejected 狀態被執行
當執行程式碼3時 丟擲錯誤
是你的錯
。then方法
promise。then(onFulfilled, onRejected)
初始化Promise時,執行器函式已經改變了Promise的狀態。且執行器函式是同步執行的。非同步操作返回的資料(成功的值和失敗的原因)可以交給。then處理,為Promise例項提供處理程式。
Promise例項生成以後,可以用then方法分別指定
resolved狀態
和
rejected狀態
的回撥函式。這兩個函式
onFulfilled,onRejected
都是可選的,不一定要提供。如果提供,則會Promise分別進入
resolved狀態
和
rejected狀態
時執行。
而且任何傳給then方法的
非函式型別引數
都會被靜默忽略。
then 方法必須返回一個
新的 promise 物件
(實現鏈式呼叫的關鍵)
實現原理
Promise只能轉換最終狀態一次,所以
onFulfilled
和
onRejected
兩個引數的操作是
互斥
的
當狀態state為
fulfilled
,則執行
onFulfilled
,傳入
this.value
。當狀態state為
rejected
,則執行
onRejected
,傳入
this.reason
class Promise { constructor(executor) { this。state = ‘pending’ // 初始化 未完成狀態 // 成功的值 this。value = undefined; // 失敗的原因 this。reason = undefined; // 。then 立即執行後 state為pengding 把。then儲存起來 this。onResolvedCallbacks = []; this。onRejectedCallbacks = []; // 把非同步任務 把結果交給 resolve let resolve = (value) => { if (this。state === ‘pending’) { console。log(‘fulfilled 狀態被執行’); this。value = value this。state = ‘fulfilled’ // onFulfilled 要執行一次 this。onResolvedCallbacks。forEach(fn => fn()); } } let reject = (reason) => { if (this。state === ‘pending’) { console。log(‘rejected 狀態被執行’); this。reason = reason this。state = ‘rejected’ this。onRejectedCallbacks。forEach(fn => fn()); } } try { executor(resolve, reject) } catch (e) { reject(err) } } // 一個promise解決了後(完成狀態轉移,把控制權交出來) then(onFulfilled, onRejected) { if (this。state == ‘pending’) { this。onResolvedCallbacks。push(() => { onFulfilled(this。value) }) this。onRejectedCallbacks。push(() => { onRejected(this。reason) }) } console。log(‘then’); // 狀態為fulfilled 執行成功 傳入成功後的回撥 把執行權轉移 if (this。state == ‘fulfiiied’) { onFulfilled(this。value); } // 狀態為rejected 執行失敗 傳入失敗後的回撥 把執行權轉移 if (this。state == ‘rejected’) { onRejected(this。reason) } }}let p1 = new Promise((resolve, reject) => { console。log(0); setTimeout(() => { // resolve(10) reject(‘JS我不愛你了’) console。log(‘setTimeout’); }, 1000)})。then(null,(data) => { console。log(data, ‘++++++++++’);})複製程式碼
0thenrejected 狀態被執行JS我不愛你了 ++++++++++setTimeout複製程式碼
當resolve在setTomeout內執行,then時state還是pending等待狀態 我們就需要在then呼叫的時候,將成功和失敗存到各自的陣列,一旦reject或者resolve,就呼叫它們。
現可以非同步實現了,但是還是不能鏈式呼叫啊? 為保證 then 函式鏈式呼叫,
then 需要返回 promise 例項
,再把這個promise返回的值傳入下一個then中。
Promise的各種方法
Promise。prototype。catch()
catch 異常處理函式,處理前面回撥中可能丟擲的異常。只接收一個引數
onRejected
處理程式。它相當於呼叫Promise。prototype。then(null,onRejected),所以它
也會返回一個新的Promise
例如
let p = new Promise((resolve, reject) => { setTimeout(() => { resolve(10) }, 1000)})。then(() => { throw Error(“1123”)})。catch((err) => { console。log(err);})。then(() => { console。log(‘異常捕獲後可以繼續。then’);})複製程式碼
當第一個。then的異常被捕獲後可以繼續執行。
Promise。all()
Promise。all()建立的Promise會在這一組Promise全部解決後在解決。也就是說會等待所有的promise程式都返回結果之後執行後續的程式。返回一個新的Promise。
例如
let p1 = new Promise((resolve, reject) => { resolve(‘success1’)})let p2 = new Promise((resolve, reject) => { resolve(‘success1’)})// let p3 = Promise。reject(‘failed3’)Promise。all([p1, p2])。then((result) => { console。log(result) // [‘success1’, ‘success2’] })。catch((error) => { console。log(error)})// Promise。all([p1,p3,p2])。then((result) => { // console。log(result)// })。catch((error) => { // console。log(error) // ‘failed3’ // // })複製程式碼
有上述例子得到,all的性質:
如果所有都成功,則合成Promise的返回值就是所有子Promise的返回值陣列。
如果有一個失敗,那麼第一個失敗的會把自己的理由作為合成Promise的失敗理由。
Promise。race()
Promise。race()是一組集合中最先解決或最先拒絕的Promise,返回一個新的Promise。
例如
let p1 = new Promise((resolve, reject) => { setTimeout(() => { resolve(‘success1’) },1000)})let p2 = new Promise((resolve, reject) => { setTimeout(() => { reject(‘failed2’) }, 1500)})Promise。race([p1, p2])。then((result) => { console。log(result)})。catch((error) => { console。log(error) // ‘success1’ })複製程式碼
有上述例子得到,race的性質:
無論如何,最先執行完成的,就執行相應後面的。then或者。catch。誰先以誰作為回撥
總結
上面的Promise就總結到這裡有什麼理解也可以在下方評論區一起交流學習。
面試可以讓自己發現更多的知識盲點,從而促進自己學習,大家一起加油衝呀!!
這篇文章小夥伴們也別忘了
點贊+評論
噢!!!