<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Promise必備知識匯總和面試情況

          共 26096字,需瀏覽 53分鐘

           ·

          2021-06-08 12:54

          點擊上方 程序員成長指北,關(guān)注公眾號

          回復(fù)1,加入高級 Node 進階交流群

          來源:https://segmentfault.com/a/1190000039699000

          作者:小磊

          寫在前面

          Javascript異步編程先后經(jīng)歷了四個階段,分別是Callback階段,Promise階段,Generator階段和Async/Await階段。Callback很快就被發(fā)現(xiàn)存在回調(diào)地獄和控制權(quán)問題,Promise就是在這個時間出現(xiàn),用以解決這些問題,Promise并非一個新事務(wù),而是按照一個規(guī)范實現(xiàn)的類,這個規(guī)范有很多,如 Promise/A,Promise/BPromise/D以及 Promise/A 的升級版 Promise/A+,最終 ES6 中采用了 Promise/A+ 規(guī)范。后來出現(xiàn)的Generator函數(shù)以及Async函數(shù)也是以Promise為基礎(chǔ)的進一步封裝,可見Promise在異步編程中的重要性。

          關(guān)于Promise的資料已經(jīng)很多,但每個人理解都不一樣,不同的思路也會有不一樣的收獲。這篇文章會著重寫一下Promise的實現(xiàn)以及筆者在日常使用過程中的一些心得體會。

          實現(xiàn)Promise

          規(guī)范解讀

          Promise/A+規(guī)范主要分為術(shù)語、要求和注意事項三個部分,我們重點看一下第二部分也就是要求部分,以筆者的理解大概說明一下,具體細節(jié)參照完整版Promise/A+標準。

          1、Promise有三種狀態(tài)pendingfulfilledrejected。(為了一致性,此文章稱fulfilled狀態(tài)為resolved狀態(tài))

          • 狀態(tài)轉(zhuǎn)換只能是pendingresolved或者pendingrejected;
          • 狀態(tài)一旦轉(zhuǎn)換完成,不能再次轉(zhuǎn)換。

          2、Promise擁有一個then方法,用以處理resolvedrejected狀態(tài)下的值。

          • then方法接收兩個參數(shù)onFulfilledonRejected,這兩個參數(shù)變量類型是函數(shù),如果不是函數(shù)將會被忽略,并且這兩個參數(shù)都是可選的。
          • then方法必須返回一個新的promise,記作promise2,這也就保證了then方法可以在同一個promise上多次調(diào)用。(ps:規(guī)范只要求返回promise,并沒有明確要求返回一個新的promise,這里為了跟ES6實現(xiàn)保持一致,我們也返回一個新promise
          • onResolved/onRejected有返回值則把返回值定義為x,并執(zhí)行[[Resolve]](promise2, x);
          • onResolved/onRejected運行出錯,則把promise2設(shè)置為rejected狀態(tài);
          • onResolved/onRejected不是函數(shù),則需要把promise1的狀態(tài)傳遞下去。

          3、不同的promise實現(xiàn)可以的交互。

          • 規(guī)范中稱這一步操作為promise解決過程,函數(shù)標示為[[Resolve]](promise, x),promise為要返回的新promise對象,xonResolved/onRejected的返回值。如果xthen方法且看上去像一個promise,我們就把x當(dāng)成一個promise的對象,即thenable對象,這種情況下嘗試讓promise接收x的狀態(tài)。如果x不是thenable對象,就用x的值來執(zhí)行 promise。
          • [[Resolve]](promise, x)函數(shù)具體運行規(guī)則:
            • 如果 promise 和 x 指向同一對象,以 TypeError 為據(jù)因拒絕執(zhí)行 promise;
            • 如果 x 為 Promise ,則使 promise 接受 x 的狀態(tài);
            • 如果 x 為對象或者函數(shù),取x.then的值,如果取值時出現(xiàn)錯誤,則讓promise進入rejected狀態(tài),如果then不是函數(shù),說明x不是thenable對象,直接以x的值resolve,如果then存在并且為函數(shù),則把x作為then函數(shù)的作用域this調(diào)用,then方法接收兩個參數(shù),resolvePromiserejectPromise,如果resolvePromise被執(zhí)行,則以resolvePromise的參數(shù)value作為x繼續(xù)調(diào)用[[Resolve]](promise, value),直到x不是對象或者函數(shù),如果rejectPromise被執(zhí)行則讓promise進入rejected狀態(tài);
            • 如果 x 不是對象或者函數(shù),直接就用x的值來執(zhí)行promise

          代碼實現(xiàn)

          規(guī)范解讀第1條,代碼實現(xiàn):

          class Promise {
            // 定義Promise狀態(tài),初始值為pending
            status = 'pending';
            // 狀態(tài)轉(zhuǎn)換時攜帶的值,因為在then方法中需要處理Promise成功或失敗時的值,所以需要一個全局變量存儲這個值
            data = '';

            // Promise構(gòu)造函數(shù),傳入?yún)?shù)為一個可執(zhí)行的函數(shù)
            constructor(executor) {
              // resolve函數(shù)負責(zé)把狀態(tài)轉(zhuǎn)換為resolved
              function resolve(value) {
                this.status = 'resolved';
                this.data = value;
              }
              // reject函數(shù)負責(zé)把狀態(tài)轉(zhuǎn)換為rejected
              function reject(reason) {
                this.status = 'rejected';
                this.data = reason;
              }

              // 直接執(zhí)行executor函數(shù),參數(shù)為處理函數(shù)resolve, reject。因為executor執(zhí)行過程有可能會出錯,錯誤情況需要執(zhí)行reject
              try {
                executor(resolve, reject);
              } catch(e) {
                reject(e)
              }
            }
          }

          第1條就是實現(xiàn)完畢了,相對簡單,配合代碼注釋很容易理解。

          規(guī)范解讀第2條,代碼實現(xiàn):

            /**
              * 擁有一個then方法
              * then方法提供:狀態(tài)為resolved時的回調(diào)函數(shù)onResolved,狀態(tài)為rejected時的回調(diào)函數(shù)onRejected
              * 返回一個新的Promise
            */
            then(onResolved, onRejected) {
              // 設(shè)置then的默認參數(shù),默認參數(shù)實現(xiàn)Promise的值的穿透
              onResolved = typeof onResolved === 'function' ? onResolved : function(v) { return e };
              onRejected = typeof onRejected === 'function' ? onRejected : function(e) { throw e };
              
              let promise2;
              
              promise2 =  new Promise((resolve, reject) => {
                // 如果狀態(tài)為resolved,則執(zhí)行onResolved
                if (this.status === 'resolved') {
                  try {
                    // onResolved/onRejected有返回值則把返回值定義為x
                    const x = onResolved(this.data);
                    // 執(zhí)行[[Resolve]](promise2, x)
                    resolvePromise(promise2, x, resolve, reject);
                  } catch (e) {
                    reject(e);
                  }
                }
                // 如果狀態(tài)為rejected,則執(zhí)行onRejected
                if (this.status === 'rejected') {
                  try {
                    const x = onRejected(this.data);
                    resolvePromise(promise2, x, resolve, reject);
                  } catch (e) {
                    reject(e);
                  }
                }
              });
              
              return promise2;
            }

          現(xiàn)在我們就按照規(guī)范解讀第2條,實現(xiàn)了上述代碼,上述代碼很明顯是有問題的,問題如下

          1. resolvePromise未定義;
          2. then方法執(zhí)行的時候,promise可能仍然處于pending狀態(tài),因為executor中可能存在異步操作(實際情況大部分為異步操作),這樣就導(dǎo)致onResolved/onRejected失去了執(zhí)行時機;
          3. onResolved/onRejected這兩個函數(shù)需要異步調(diào)用(官方Promise實現(xiàn)的回調(diào)函數(shù)總是異步調(diào)用的)。

          解決辦法:

          1. 根據(jù)規(guī)范解讀第3條,定義并實現(xiàn)resolvePromise函數(shù);
          2. then方法執(zhí)行時如果promise仍然處于pending狀態(tài),則把處理函數(shù)進行儲存,等resolve/reject函數(shù)真正執(zhí)行的的時候再調(diào)用。
          3. promise.then屬于微任務(wù),這里我們?yōu)榱朔奖?,用宏任?wù)setTiemout來代替實現(xiàn)異步,具體細節(jié)特別推薦這篇文章

          好了,有了解決辦法,我們就把代碼進一步完善:

          class Promise {
            // 定義Promise狀態(tài)變量,初始值為pending
            status = 'pending';
            // 因為在then方法中需要處理Promise成功或失敗時的值,所以需要一個全局變量存儲這個值
            data = '';
            // Promise resolve時的回調(diào)函數(shù)集
            onResolvedCallback = [];
            // Promise reject時的回調(diào)函數(shù)集
            onRejectedCallback = [];

            // Promise構(gòu)造函數(shù),傳入?yún)?shù)為一個可執(zhí)行的函數(shù)
            constructor(executor) {
              // resolve函數(shù)負責(zé)把狀態(tài)轉(zhuǎn)換為resolved
              function resolve(value) {
                this.status = 'resolved';
                this.data = value;
                for (const func of this.onResolvedCallback) {
                  func(this.data);
                }
              }
              // reject函數(shù)負責(zé)把狀態(tài)轉(zhuǎn)換為rejected
              function reject(reason) {
                this.status = 'rejected';
                this.data = reason;
                for (const func of this.onRejectedCallback) {
                  func(this.data);
                }
              }

              // 直接執(zhí)行executor函數(shù),參數(shù)為處理函數(shù)resolve, reject。因為executor執(zhí)行過程有可能會出錯,錯誤情況需要執(zhí)行reject
              try {
                executor(resolve, reject);
              } catch(e) {
                reject(e)
              }
            }
            /**
              * 擁有一個then方法
              * then方法提供:狀態(tài)為resolved時的回調(diào)函數(shù)onResolved,狀態(tài)為rejected時的回調(diào)函數(shù)onRejected
              * 返回一個新的Promise
            */
            then(onResolved, onRejected) {

              // 設(shè)置then的默認參數(shù),默認參數(shù)實現(xiàn)Promise的值的穿透
              onResolved = typeof onResolved === 'function' ? onResolved : function(v) { return e };
              onRejected = typeof onRejected === 'function' ? onRejected : function(e) { throw e };

              let promise2;

              promise2 =  new Promise((resolve, reject) => {
                // 如果狀態(tài)為resolved,則執(zhí)行onResolved
                if (this.status === 'resolved') {
                  setTimeout(() => {
                    try {
                      // onResolved/onRejected有返回值則把返回值定義為x
                      const x = onResolved(this.data);
                      // 執(zhí)行[[Resolve]](promise2, x)
                      this.resolvePromise(promise2, x, resolve, reject);
                    } catch (e) {
                      reject(e);
                    }
                  }, 0);
                }
                // 如果狀態(tài)為rejected,則執(zhí)行onRejected
                if (this.status === 'rejected') {
                  setTimeout(() => {
                    try {
                      const x = onRejected(this.data);
                      this.resolvePromise(promise2, x, resolve, reject);
                    } catch (e) {
                      reject(e);
                    }
                  }, 0);
                }
                // 如果狀態(tài)為pending,則把處理函數(shù)進行存儲
                if (this.status = 'pending') {
                  this.onResolvedCallback.push(() => {
                    setTimeout(() => {
                      try {
                        const x = onResolved(this.data);
                        this.resolvePromise(promise2, x, resolve, reject);
                      } catch (e) {
                        reject(e);
                      }
                    }, 0);
                  });

                  this.onRejectedCallback.push(() => {
                    setTimeout(() => {
                      try {
                        const x = onRejected(this.data);
                        this.resolvePromise(promise2, x, resolve, reject);
                      } catch (e) {
                        reject(e);
                      }
                    }, 0);
                  });
                }

              });

              return promise2;
            }

            // [[Resolve]](promise2, x)函數(shù)
            resolvePromise(promise2, x, resolve, reject) {
              
            }
            
          }

          至此,規(guī)范中關(guān)于then的部分就全部實現(xiàn)完畢了。代碼添加了詳細的注釋,參考注釋不難理解。

          規(guī)范解讀第3條,代碼實現(xiàn):

          // [[Resolve]](promise2, x)函數(shù)
            resolvePromise(promise2, x, resolve, reject) {
              let called = false;

              if (promise2 === x) {
                return reject(new TypeError('Chaining cycle detected for promise!'))
              }
              
              // 如果x仍然為Promise的情況
              if (x instanceof Promise) {
                // 如果x的狀態(tài)還沒有確定,那么它是有可能被一個thenable決定最終狀態(tài)和值,所以需要繼續(xù)調(diào)用resolvePromise
                if (x.status === 'pending') {
                  x.then(function(value) {
                    resolvePromise(promise2, value, resolve, reject)
                  }, reject)
                } else { 
                  // 如果x狀態(tài)已經(jīng)確定了,直接取它的狀態(tài)
                  x.then(resolve, reject)
                }
                return
              }
            
              if (x !== null && (Object.prototype.toString(x) === '[object Object]' || Object.prototype.toString(x) === '[object Function]')) {
                try {
                  // 因為x.then有可能是一個getter,這種情況下多次讀取就有可能產(chǎn)生副作用,所以通過變量called進行控制
                  const then = x.then 
                  // then是函數(shù),那就說明x是thenable,繼續(xù)執(zhí)行resolvePromise函數(shù),直到x為普通值
                  if (typeof then === 'function') { 
                    then.call(x, (y) => { 
                      if (called) return;
                      called = true;
                      this.resolvePromise(promise2, y, resolve, reject);
                    }, (r) => {
                      if (called) return;
                      called = true;
                      reject(r);
                    })
                  } else { // 如果then不是函數(shù),那就說明x不是thenable,直接resolve x
                    if (called) return ;
                    called = true;
                    resolve(x);
                  }
                } catch (e) {
                  if (called) return;
                  called = true;
                  reject(e);
                }
              } else {
                resolve(x);
              }
            }

          這一步驟非常簡單,只要按照規(guī)范轉(zhuǎn)換成代碼即可。

          最后,完整的Promise按照規(guī)范就實現(xiàn)完畢了,是的,規(guī)范里并沒有規(guī)定catch、Promise.resolve、Promise.reject、Promise.all等方法,接下來,我們就看一看Promise的這些常用方法。

          Promise其他方法實現(xiàn)

          1、catch方法

          catch方法是對then方法的封裝,只用于接收reject(reason)中的錯誤信息。因為在then方法中onRejected參數(shù)是可不傳的,不傳的情況下,錯誤信息會依次往后傳遞,直到有onRejected函數(shù)接收為止,因此在寫promise鏈式調(diào)用的時候,then方法不傳onRejected函數(shù),只需要在最末尾加一個catch()就可以了,這樣在該鏈條中的promise發(fā)生的錯誤都會被最后的catch捕獲到。

            catch(onRejected) {
              return this.then(null, onRejected);
            }
          2、done方法

          catchpromise鏈式調(diào)用的末尾調(diào)用,用于捕獲鏈條中的錯誤信息,但是catch方法內(nèi)部也可能出現(xiàn)錯誤,所以有些promise實現(xiàn)中增加了一個方法done,done相當(dāng)于提供了一個不會出錯的catch方法,并且不再返回一個promise,一般用來結(jié)束一個promise鏈。

            done() {
              this.catch(reason => {
                console.log('done', reason);
                throw reason;
              });
            }
          3、finally方法

          finally方法用于無論是resolve還是reject,finally的參數(shù)函數(shù)都會被執(zhí)行。

            finally(fn) {
              return this.then(value => {
                fn();
                return value;
              }, reason => {
                fn();
                throw reason;
              });
            };
          4、Promise.all方法

          Promise.all方法接收一個promise數(shù)組,返回一個新promise2,并發(fā)執(zhí)行數(shù)組中的全部promise,所有promise狀態(tài)都為resolved時,promise2狀態(tài)為resolved并返回全部promise結(jié)果,結(jié)果順序和promise數(shù)組順序一致。如果有一個promiserejected狀態(tài),則整個promise2進入rejected狀態(tài)。

            static all(promiseList) {
              return new Promise((resolve, reject) => {
                const result = [];
                let i = 0;
                for (const p of promiseList) {
                  p.then(value => {
                    result[i] = value;
                    if (result.length === promiseList.length) {
                      resolve(result);
                    }
                  }, reject);
                  i++;
                }
              });
            }
          5、Promise.race方法

          Promise.race方法接收一個promise數(shù)組, 返回一個新promise2,順序執(zhí)行數(shù)組中的promise,有一個promise狀態(tài)確定,promise2狀態(tài)即確定,并且同這個promise的狀態(tài)一致。

            static race(promiseList) {
              return new Promise((resolve, reject) => {
                for (const p of promiseList) {
                  p.then((value) => {
                    resolve(value);   
                  }, reject);
                }
              });
            }
          6、Promise.resolve方法/Promise.reject

          Promise.resolve用來生成一個rejected完成態(tài)的promise,Promise.reject用來生成一個rejected失敗態(tài)的promise

            static resolve(value) {
              let promise;

              promise = new Promise((resolve, reject) => {
                this.resolvePromise(promise, value, resolve, reject);
              });
            
              return promise;
            }
            
            static reject(reason) {
              return new Promise((resolve, reject) => {
                reject(reason);
              });
            }

          常用的方法基本就這些,Promise還有很多擴展方法,這里就不一一展示,基本上都是對then方法的進一步封裝,只要你的then方法沒有問題,其他方法就都可以依賴then方法實現(xiàn)。

          Promise面試相關(guān)

          面試相關(guān)問題,筆者只說一下我司這幾年的情況,并不能代表全部情況,參考即可。Promise是我司前端開發(fā)職位,nodejs開發(fā)職位,全棧開發(fā)職位,必問的一個知識點,主要問題會分布在Promise介紹、基礎(chǔ)使用方法以及深層次的理解三個方面,問題一般在3-5個,根據(jù)面試者回答情況會適當(dāng)增減。

          1、簡單介紹下Promise。

          Promise 是異步編程的一種解決方案,比傳統(tǒng)的解決方案——回調(diào)函數(shù)和事件——更合理和更強大。它由社區(qū)最早提出和實現(xiàn),ES6 將其寫進了語言標準,統(tǒng)一了用法,原生提供了Promise對象。有了Promise對象,就可以將異步操作以同步操作的流程表達出來,避免了層層嵌套的回調(diào)函數(shù)。此外,Promise對象提供統(tǒng)一的接口,使得控制異步操作更加容易。(當(dāng)然了也可以簡單介紹promise狀態(tài),有什么方法,callback存在什么問題等等,這個問題是比較開放的)

          • 提問概率:99%
          • 評分標準:人性化判斷即可,此問題一般作為引入問題。
          • 加分項:熟練說出Promise具體解決了那些問題,存在什么缺點,應(yīng)用方向等等。
          2、實現(xiàn)一個簡單的,支持異步鏈式調(diào)用的Promise類。

          這個答案不是固定的,可以參考最簡實現(xiàn) Promise,支持異步鏈式調(diào)用

          • 提問概率:50%(手擼代碼題,因為這類題目比較耗費時間,一場面試并不會出現(xiàn)很多,所以出現(xiàn)頻率不是很高,但卻是必備知識)
          • 加分項:基本功能實現(xiàn)的基礎(chǔ)上有onResolved/onRejected函數(shù)異步調(diào)用,錯誤捕獲合理等亮點。
          3、Promise.then在Event Loop中的執(zhí)行順序。(可以直接問,也可以出具體題目讓面試者回答打印順序)

          JS中分為兩種任務(wù)類型:macrotaskmicrotask,其中macrotask包含:主代碼塊,setTimeout,setInterval,setImmediate等(setImmediate規(guī)定:在下一次Event Loop(宏任務(wù))時觸發(fā));microtask包含:Promise,process.nextTick等(在node環(huán)境下,process.nextTick的優(yōu)先級高于PromiseEvent Loop中執(zhí)行一個macrotask任務(wù)(棧中沒有就從事件隊列中獲?。﹫?zhí)行過程中如果遇到microtask任務(wù),就將它添加到微任務(wù)的任務(wù)隊列中,macrotask任務(wù)執(zhí)行完畢后,立即執(zhí)行當(dāng)前微任務(wù)隊列中的所有microtask任務(wù)(依次執(zhí)行),然后開始下一個macrotask任務(wù)(從事件隊列中獲?。?瀏覽器運行機制可參考這篇文章

          • 提問概率:75%(可以理解為4次面試中3次會問到,順便可以考察面試者對JS運行機制的理解)
          • 加分項:擴展講述瀏覽器運行機制。
          4、闡述Promise的一些靜態(tài)方法。

          Promise.deferred、Promise.allPromise.race、Promise.resolve、Promise.reject

          • 提問概率:25%(相對基礎(chǔ)的問題,一般在其他問題回答不是很理想的情況下提問,或者為了引出下一個題目而提問)
          • 加分項:越多越好
          5、Promise存在哪些缺點。

          1、無法取消Promise,一旦新建它就會立即執(zhí)行,無法中途取消。2、如果不設(shè)置回調(diào)函數(shù),Promise內(nèi)部拋出的錯誤,不會反應(yīng)到外部。3、吞掉錯誤或異常,錯誤只能順序處理,即便在Promise鏈最后添加catch方法,依然可能存在無法捕捉的錯誤(catch內(nèi)部可能會出現(xiàn)錯誤) 4、閱讀代碼不是一眼可以看懂,你只會看到一堆then,必須自己在then的回調(diào)函數(shù)里面理清邏輯。

          • 提問概率:25%(此問題作為提高題目,出現(xiàn)概率不高)
          • 加分項:越多越合理越好(網(wǎng)上有很多說法,不一一佐證) (此題目,歡迎大家補充答案)
          6、使用Promise進行順序(sequence)處理。

          1、使用async函數(shù)配合await或者使用generator函數(shù)配合yield。2、使用promise.then通過for循環(huán)或者Array.prototype.reduce實現(xiàn)。

          function sequenceTasks(tasks) {
              function recordValue(results, value) {
                  results.push(value);
                  return results;
              }
              var pushValue = recordValue.bind(null, []);
              return tasks.reduce(function (promise, task) {
                  return promise.then(() => task).then(pushValue);
              }, Promise.resolve());
          }
          • 提問概率:90%(我司提問概率極高的題目,即能考察面試者對promise的理解程度,又能考察編程邏輯,最后還有bindreduce等方法的運用)
          • 評分標準:說出任意解決方法即可,其中只能說出async函數(shù)和generator函數(shù)的可以得到20%的分數(shù),可以用promise.then配合for循環(huán)解決的可以得到60%的分數(shù),配合Array.prototype.reduce實現(xiàn)的可以得到最后的20%分數(shù)。
          7、如何停止一個Promise鏈?

          在要停止的promise鏈位置添加一個方法,返回一個永遠不執(zhí)行resolve或者rejectPromise,那么這個promise永遠處于pending狀態(tài),所以永遠也不會向下執(zhí)行thencatch了。這樣我們就停止了一個promise鏈。

              Promise.cancel = Promise.stop = function() {
                return new Promise(function(){})
              }
          • 提問概率:50%(此問題主要考察面試者羅輯思維) (此題目,歡迎大家補充答案)
          8、Promise鏈上返回的最后一個Promise出錯了怎么辦?

          catchpromise鏈式調(diào)用的末尾調(diào)用,用于捕獲鏈條中的錯誤信息,但是catch方法內(nèi)部也可能出現(xiàn)錯誤,所以有些promise實現(xiàn)中增加了一個方法done,done相當(dāng)于提供了一個不會出錯的catch方法,并且不再返回一個promise,一般用來結(jié)束一個promise鏈。

            done() {
              this.catch(reason => {
                console.log('done', reason);
                throw reason;
              });
            }
          • 提問概率:90%(同樣作為出題率極高的一個題目,充分考察面試者對promise的理解程度)
          • 加分項:給出具體的done()方法代碼實現(xiàn)
          9、Promise存在哪些使用技巧或者最佳實踐?

          1、鏈式promise要返回一個promise,而不只是構(gòu)造一個promise。2、合理的使用Promise.allPromise.race等方法。3、在寫promise鏈式調(diào)用的時候,then方法不傳onRejected函數(shù),只需要在最末尾加一個catch()就可以了,這樣在該鏈條中的promise發(fā)生的錯誤都會被最后的catch捕獲到。如果catch()代碼有出現(xiàn)錯誤的可能,需要在鏈式調(diào)用的末尾增加done()函數(shù)。

          • 提問概率:10%(出題概率極低的一個題目)
          • 加分項:越多越好

          (此題目,歡迎大家補充答案)

          至此,我司關(guān)于Promise的一些面試題目就列舉完畢了,有些題目的答案是開放的,歡迎大家一起補充完善??偨Y(jié)起來,Promise作為js面試必問部分還是相對容易掌握并通過的。

          總結(jié)

          Promise作為所有js開發(fā)者的必備技能,其實現(xiàn)思路值得所有人學(xué)習(xí),通過這篇文章,希望小伙伴們在以后編碼過程中能更加熟練、更加明白的使用Promise。

          最后

          如果覺得這篇文章還不錯
          點擊下面卡片關(guān)注我
          來個【分享、點贊、在看】三連支持一下吧

             “分享、點贊在看” 支持一波  

          瀏覽 33
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  无码人要 | 蜜臀国产AV | 亚洲a在线视频 | 国产精品成人视频在线观看 | 青青操久操视频 |