摘要:答案題目三解析方法的參數(shù)如果是一個原始值,或者是一個不具有方法的對象,則方法返回一個新的對象,狀態(tài)為,方法的參數(shù),會同時傳給回調(diào)函數(shù)。
常見Promise面試題 題目一
const promise = new Promise((resolve, reject) => { console.log(1); resolve(); console.log(2); }) promise.then(() => { console.log(3); }) console.log(4);
解析
首先Promise新建后立即執(zhí)行,所以會先輸出1,2,而Promise.then()內(nèi)部的代碼在當(dāng)次事件循環(huán)的結(jié)尾立即執(zhí)行,所以會先輸出4,最后輸出3.
答案:1 2 4 3
const promise = new Promise((resolve, reject) => { resolve("success1"); reject("error"); resolve("success2"); }); promise.then((res) => { console.log("then:", res); }).catch((err) => { console.log("catch:", err); })
解析
resolve函數(shù)Promise對象的狀態(tài)從“未完成”變?yōu)椤俺晒Α保磸膒ending變?yōu)閞esolved),在異步操作成功時調(diào)用,并將異步操作的結(jié)果,作為參數(shù)傳遞出去;
reject函數(shù)將Promise對象的狀態(tài)從“未完成”變?yōu)椤笆 保磸膒ending變?yōu)閞ejected),在異步操作失敗時調(diào)用,并將異步操作報出的錯誤,作為參數(shù)傳遞出去。
而一旦狀態(tài)改變,就不會有再變。
所以代碼中的reject("error");不會有作用。
Promise只能resolve一次,剩下的調(diào)用都會被忽略。
所以第二次resolve("success");也不會有作用。
答案:then:success1
Promise.resolve(1) .then(2) .then(Promise.resolve(3)) .then(console.log)
解析
Promise.resolve方法的參數(shù)如果是一個原始值,或者是一個不具有then方法的對象,則Promise.resolve方法返回一個新的Promise對象,狀態(tài)為resolved,Promise.resolve方法的參數(shù),會同時傳給回調(diào)函數(shù)。
then方法接受的參數(shù)是函數(shù),而如果傳遞的并非是一個函數(shù),它實(shí)際上會將其解釋為then(null),這就會導(dǎo)致前一個Promise的結(jié)果會傳遞下面。
答案 1
紅燈3秒亮一次,綠燈1秒亮一次,黃燈2秒亮一次;如何讓三個燈不斷交替重復(fù)亮燈?(用Promise實(shí)現(xiàn))三個亮燈函數(shù)已經(jīng)存在:
function red() { console.log("red"); } function green() { console.log("green"); } function yellow() { console.log("yellow"); }
解析
紅燈3秒亮一次,綠燈1秒亮一次 ,黃燈2秒亮一次,意思就是3秒執(zhí)行一次red函數(shù),2秒執(zhí)行一次green函數(shù),1秒執(zhí)行一次yellow函數(shù),不斷交替重復(fù)亮燈,意思就是按照這個順序一直執(zhí)行這3個函數(shù),這步可以利用遞歸來實(shí)現(xiàn)。
答案:
function red() { console.log("red"); } function green() { console.log("green"); } function yellow() { console.log("yellow"); } var light = function (timmer, cb) { return new Promise(function (resolve, reject) { setTimeout(function () { cb(); resolve(); }, timmer); }); }; var step = function () { Promise.resolve().then(function () { return light(3000, red); }).then(function () { return light(2000, green); }).then(function () { return light(1000, yellow); }).then(function () { step(); }); } step();題目五
實(shí)現(xiàn)mergePromise函數(shù),把傳進(jìn)去的數(shù)組按順序先后執(zhí)行,并且把返回的數(shù)據(jù)先后放到數(shù)組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 => { // 在這里實(shí)現(xiàn)你的代碼 }; mergePromise([ajax1, ajax2, ajax3]).then(data => { console.log("done"); console.log(data); // data 為 [1, 2, 3] }); // 要求分別輸出 // 1 // 2 // 3 // done // [1, 2, 3]
解析
首先ajax1,ajax2,ajax3都是函數(shù),只是這些函數(shù)執(zhí)行后會返回一個Promise,按照題目要求只要順序執(zhí)行這三個函數(shù)就好了,然后把結(jié)果放到data中,但是這些函數(shù)都是異步操作,想要按順序執(zhí)行輸出1,2,3并非那么容易,舉例
function A() { setTimeout(function () { console.log("a"); }, 3000); } function B() { setTimeout(function () { console.log("b"); }, 1000); } A(); B(); // b // a
例子中按照順序執(zhí)行A,B但是輸出的結(jié)果卻是b,a。因?yàn)閷τ诋惒胶瘮?shù)來說,并不會按順序執(zhí)行完一個,再執(zhí)行后一個。
這道題主要考察用Promise控制異步流程,讓這些涵涵素,一個執(zhí)行完,再執(zhí)行下一個。
答案
// 保存數(shù)組中的函數(shù)執(zhí)行后的結(jié)果 var data = []; // Promise.resolve方法調(diào)用時不帶參數(shù),直接返回一個resolved狀態(tài)的 Promise 對象。 var sequence = Promise.resolve(); ajaxArray.forEach(function (item) { // 第一次的 then 方法用來執(zhí)行數(shù)組中的每個函數(shù), // 第二次的 then 方法接受數(shù)組中的函數(shù)執(zhí)行后返回的結(jié)果, // 并把結(jié)果添加到 data 中,然后把 data 返回。 sequence = sequence.then(item).then(function (res) { data.push(res); return data; }); }) // 遍歷結(jié)束后,返回一個 Promise,也就是 sequence, 他的 [[PromiseValue]] 值就是 data, // 而 data(保存數(shù)組中的函數(shù)執(zhí)行后的結(jié)果) 也會作為參數(shù),傳入下次調(diào)用的 then 方法中。 return sequence;題目六
以下代碼最后輸出什么
const first = () => (new Promise((resolve, reject) => { console.log(3); let p = new Promise((resolve, reject) => { console.log(7); setTimeout(() => { console.log(5); resolve(6); }, 0) resolve(1); }); resolve(2); p.then((arg) => { console.log(arg); }); })); first().then((arg) => { console.log(arg); }); console.log(4);
解析
這道題主要理解js執(zhí)行機(jī)制
第一輪事件循環(huán)
先執(zhí)行宏任務(wù),主script,new Promise立即執(zhí)行,輸出 3,
執(zhí)行p這個new Promise操作,輸出 7,
發(fā)現(xiàn)setTimeout,將回調(diào)函數(shù)放入下一輪任務(wù)隊列(Event Quene),p的then,暫且命名為then1,放入微任務(wù)隊列,且first也有then,命名為then2,放入微任務(wù)隊列。執(zhí)行console.log(4),輸出 4,宏任務(wù)執(zhí)行結(jié)束。
再執(zhí)行微任務(wù),執(zhí)行then1,輸出 1,
執(zhí)行then2,輸出 3.
第一輪事件循環(huán)結(jié)束,開始執(zhí)行第二輪。
第二輪事件循環(huán)
先執(zhí)行宏任務(wù)里面的,也就是setTimeout的回調(diào),輸出 5.
resolve(6)不會生效,因?yàn)閜的Promise狀態(tài)一旦改變就不會再變化了。
答案 3 7 4 1 2 5
有8個圖片資源的url,已經(jīng)存儲在數(shù)組urls中(即urls=["http://example.com/1.jpg",...,"http:""example.com/8.jpg"]),而且已經(jīng)有一個函數(shù)function loading,輸入一個url鏈接,返回一個Promise,該P(yáng)romise在圖片下載完成的時候resolve,下載失敗則reject。
但有一個要求,任何時刻同時下載的鏈接數(shù)量不可以超過3個。
請寫一段代碼實(shí)現(xiàn)這個需求,要求盡可能快速地將所有圖片下載完成。
var urls = ["https://www.kkkk1000.com/images/getImgData/getImgDatadata.jpg", "https://www.kkkk1000.com/images/getImgData/gray.gif", "https://www.kkkk1000.com/images/getImgData/Particle.gif", "https://www.kkkk1000.com/images/getImgData/arithmetic.png", "https://www.kkkk1000.com/images/getImgData/arithmetic2.gif", "https://www.kkkk1000.com/images/getImgData/getImgDataError.jpg", "https://www.kkkk1000.com/images/getImgData/arithmetic.gif", "https://www.kkkk1000.com/images/wxQrCode2.png"]; function loadImg(url) { return new Promise((resolve, reject) => { const img = new Image() img.onload = function () { console.log("一張圖片加載完成"); resolve(); } img.onerror = reject img.src = url }) };
解析
題目的意思是需要先并發(fā)請求3張圖片,當(dāng)一張圖片加載完成后,又會繼續(xù)發(fā)起一張圖片的請求,讓并發(fā)數(shù)保持在3個,直到需要加載的圖片都全部發(fā)起請求。
用Promise來實(shí)現(xiàn)就是,先并發(fā)請求3個圖片資源,這樣可以得到3個Promise,組成一個數(shù)組promises,然后不斷調(diào)用Promise.race來返回最快改變狀態(tài)的Promise,然后從數(shù)組promises中刪掉這個Promise對象,再加入一個新的Promise,直到全部的url被取完,最后再使用Promise.all來處理一遍數(shù)組promises中沒有改變狀態(tài)的Promise
答案
var urls = ["https://www.kkkk1000.com/images/getImgData/getImgDatadata.jpg", "https://www.kkkk1000.com/images/getImgData/gray.gif", "https://www.kkkk1000.com/images/getImgData/Particle.gif", "https://www.kkkk1000.com/images/getImgData/arithmetic.png", "https://www.kkkk1000.com/images/getImgData/arithmetic2.gif", "https://www.kkkk1000.com/images/getImgData/getImgDataError.jpg", "https://www.kkkk1000.com/images/getImgData/arithmetic.gif", "https://www.kkkk1000.com/images/wxQrCode2.png"]; function loadImg(url) { return new Promise((resolve, reject) => { const img = new Image() img.onload = function () { console.log("一張圖片加載完成"); resolve(); } img.onerror = reject img.src = url }) }; function limitLoad(urls, handler, limit) { // 對數(shù)組做一個拷貝 const sequence = [].concat(urls) let promises = []; //并發(fā)請求到最大數(shù) promises = sequence.splice(0, limit).map((url, index) => { // 這里返回的 index 是任務(wù)在 promises 的腳標(biāo),用于在 Promise.race 之后找到完成的任務(wù)腳標(biāo) return handler(url).then(() => { return index }); }); // 利用數(shù)組的 reduce 方法來以隊列的形式執(zhí)行 return sequence.reduce((last, url, currentIndex) => { return last.then(() => { // 返回最快改變狀態(tài)的 Promise return Promise.race(promises) }).catch(err => { // 這里的 catch 不僅用來捕獲 前面 then 方法拋出的錯誤 // 更重要的是防止中斷整個鏈?zhǔn)秸{(diào)用 console.error(err) }).then((res) => { // 用新的 Promise 替換掉最快改變狀態(tài)的 Promise promises[res] = handler(sequence[currentIndex]).then(() => { return res }); }) }, Promise.resolve()).then(() => { return Promise.all(promises) }) } limitLoad(urls, loadImg, 3) /* 因?yàn)?limitLoad 函數(shù)也返回一個 Promise,所以當(dāng) 所有圖片加載完成后,可以繼續(xù)鏈?zhǔn)秸{(diào)用 limitLoad(urls, loadImg, 3).then(() => { console.log("所有圖片加載完成"); }).catch(err => { console.error(err); }) */題目八
封裝一個異步加載圖片的方法
function loadImageAsync(url) { return new Promise(function(resolve,reject) { var image = new Image(); image.onload = function() { resolve(image) }; image.onerror = function() { reject(new Error("Could not load image at" + url)); }; image.src = url; }); }
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/101105.html
摘要:前文該系列下的前幾篇文章分別對不同的幾種異步方案原理進(jìn)行解析,本文將介紹一些實(shí)際場景和一些常見的面試題。流程調(diào)度里比較常見的一種錯誤是看似串行的寫法,可以感受一下這個例子判斷以下幾種寫法的輸出結(jié)果辨別輸出順序這類題目一般出現(xiàn)在面試題里。 前文 該系列下的前幾篇文章分別對不同的幾種異步方案原理進(jìn)行解析,本文將介紹一些實(shí)際場景和一些常見的面試題。(積累不太夠,后面想到再補(bǔ)) 正文 流程調(diào)度...
摘要:不過幸運(yùn)的是所有面試的公司都給了,在這里總結(jié)下經(jīng)驗(yàn)吧。這里推薦下我當(dāng)時看的一篇的面經(jīng),木易楊老師寫的大廠高級前端面試題匯總。 前言 本人畢業(yè)一年,最近陸續(xù)面試了頭條、瓜子、360、猿輔導(dǎo)、中信銀行、老虎等公司,由于最近比較寒冬而且招1-3年的并不多,再加上自己對公司規(guī)模和位置有一定要求,所以最后合適的也就這幾家了。不過幸運(yùn)的是所有面試的公司都給了offer,在這里總結(jié)下經(jīng)驗(yàn)吧。掘金:h...
摘要:并總結(jié)經(jīng)典面試題集各種算法和插件前端視頻源碼資源于一身的文檔,優(yōu)化項(xiàng)目,在瀏覽器端的層面上提升速度,幫助初中級前端工程師快速搭建項(xiàng)目。 本文是關(guān)注微信小程序的開發(fā)和面試問題,由基礎(chǔ)到困難循序漸進(jìn),適合面試和開發(fā)小程序。并總結(jié)vue React html css js 經(jīng)典面試題 集各種算法和插件、前端視頻源碼資源于一身的文檔,優(yōu)化項(xiàng)目,在瀏覽器端的層面上提升速度,幫助初中級前端工程師快...
閱讀 3214·2021-11-11 16:54
閱讀 2377·2021-09-04 16:48
閱讀 3304·2019-08-29 16:08
閱讀 707·2019-08-29 15:13
閱讀 1436·2019-08-29 15:09
閱讀 2730·2019-08-29 12:45
閱讀 1990·2019-08-29 12:12
閱讀 512·2019-08-26 18:27