自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

帶你寫出符合Promise/A+ 規(guī)范Promise的源碼

開(kāi)發(fā) 前端
Promise是前端面試中的高頻問(wèn)題,如果你能根據(jù)PromiseA+的規(guī)范,寫出符合規(guī)范的源碼,那么我想,對(duì)于面試中的Promise相關(guān)的問(wèn)題,都能夠給出比較完美的答案。

 Promise是前端面試中的高頻問(wèn)題,如果你能根據(jù)PromiseA+的規(guī)范,寫出符合規(guī)范的源碼,那么我想,對(duì)于面試中的Promise相關(guān)的問(wèn)題,都能夠給出比較完美的答案。

我的建議是,對(duì)照規(guī)范多寫幾次實(shí)現(xiàn),也許第一遍的時(shí)候,是改了多次,才能通過(guò)測(cè)試,那么需要反復(fù)的寫,我已經(jīng)將Promise的源碼實(shí)現(xiàn)寫了不下七遍,不那么聰明的話,當(dāng)然需要更加努力啦~

[[335576]]

Promise的源碼實(shí)現(xiàn) 

  1. /**  
  2.  * 1. new Promise時(shí),需要傳遞一個(gè) executor 執(zhí)行器,執(zhí)行器立刻執(zhí)行  
  3.  * 2. executor 接受兩個(gè)參數(shù),分別是 resolve 和 reject 
  4.  * 3. promise 只能從 pending 到 rejected, 或者從 pending 到 fulfilled  
  5.  * 4. promise 的狀態(tài)一旦確認(rèn),就不會(huì)再改變  
  6.  * 5. promise 都有 then 方法,then 接收兩個(gè)參數(shù),分別是 promise 成功的回調(diào) onFulfilled,   
  7.  *      和 promise 失敗的回調(diào) onRejected  
  8.  * 6. 如果調(diào)用 then 時(shí),promise已經(jīng)成功,則執(zhí)行 onFulfilled,并將promise的值作為參數(shù)傳遞進(jìn)去。  
  9.  *      如果promise已經(jīng)失敗,那么執(zhí)行 onRejected, 并將 promise 失敗的原因作為參數(shù)傳遞進(jìn)去。  
  10.  *      如果promise的狀態(tài)是pending,需要將onFulfilled和onRejected函數(shù)存放起來(lái),等待狀態(tài)確定后,再依次將對(duì)應(yīng)的函數(shù)執(zhí)行(發(fā)布訂閱)  
  11.  * 7. then 的參數(shù) onFulfilled 和 onRejected 可以缺省  
  12.  * 8. promise 可以then多次,promise 的then 方法返回一個(gè) promise  
  13.  * 9. 如果 then 返回的是一個(gè)結(jié)果,那么就會(huì)把這個(gè)結(jié)果作為參數(shù),傳遞給下一個(gè)then的成功的回調(diào)(onFulfilled)  
  14.  * 10. 如果 then 中拋出了異常,那么就會(huì)把這個(gè)異常作為參數(shù),傳遞給下一個(gè)then的失敗的回調(diào)(onRejected)  
  15.  * 11.如果 then 返回的是一個(gè)promise,那么會(huì)等這個(gè)promise執(zhí)行完,promise如果成功,  
  16.  *   就走下一個(gè)then的成功,如果失敗,就走下一個(gè)then的失敗  
  17.  */  
  18. const PENDING = 'pending' 
  19. const FULFILLED = 'fulfilled' 
  20. const REJECTED = 'rejected' 
  21. function Promise(executor) {  
  22.     let self = this 
  23.     self.status = PENDING 
  24.     self.onFulfilled = [];//成功的回調(diào)  
  25.     self.onRejected = []; //失敗的回調(diào)  
  26.     //PromiseA+ 2.1  
  27.     function resolve(value) {  
  28.         if (self.status === PENDING) {  
  29.             self.status = FULFILLED 
  30.             self.value = value;  
  31.             self.onFulfilled.forEach(fn => fn());//PromiseA+ 2.2.6.1  
  32.         }  
  33.     }  
  34.     function reject(reason) {  
  35.         if (self.status === PENDING) {  
  36.             self.status = REJECTED 
  37.             self.reason = reason;  
  38.             self.onRejected.forEach(fn => fn());//PromiseA+ 2.2.6.2  
  39.         } 
  40.      } 
  41.     try {  
  42.         executor(resolve, reject);  
  43.     } catch (e) {  
  44.         reject(e);  
  45.     }  
  46.  
  47. Promise.prototype.then = function (onFulfilled, onRejected) {  
  48.     //PromiseA+ 2.2.1 / PromiseA+ 2.2.5 / PromiseA+ 2.2.7.3 / PromiseA+ 2.2.7.4  
  49.     onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;  
  50.     onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason };  
  51.     let self = this 
  52.     //PromiseA+ 2.2.7  
  53.     let promise2 = new Promise((resolve, reject) => {  
  54.         if (self.status === FULFILLED) {  
  55.             //PromiseA+ 2.2.2  
  56.             //PromiseA+ 2.2.4 --- setTimeout  
  57.             setTimeout(() => {  
  58.                 try {  
  59.                     //PromiseA+ 2.2.7.1  
  60.                     let x = onFulfilled(self.value);  
  61.                     resolvePromise(promise2, x, resolve, reject);  
  62.                 } catch (e) {  
  63.                     //PromiseA+ 2.2.7.2  
  64.                     reject(e);  
  65.                 }  
  66.             });  
  67.         } else if (self.status === REJECTED) {  
  68.             //PromiseA+ 2.2.3  
  69.             setTimeout(() => {  
  70.                 try {  
  71.                     let x = onRejected(self.reason);  
  72.                     resolvePromise(promise2, x, resolve, reject);  
  73.                 } catch (e) {  
  74.                     reject(e);  
  75.                 }  
  76.             });  
  77.         } else if (self.status === PENDING) {  
  78.             self.onFulfilled.push(() => {  
  79.                 setTimeout(() => {  
  80.                     try {  
  81.                         let x = onFulfilled(self.value);  
  82.                         resolvePromise(promise2, x, resolve, reject);  
  83.                     } catch (e) {  
  84.                         reject(e);  
  85.                     }  
  86.                 });  
  87.             });  
  88.             self.onRejected.push(() => {  
  89.                 setTimeout(() => {  
  90.                     try {  
  91.                         let x = onRejected(self.reason);  
  92.                         resolvePromise(promise2, x, resolve, reject);  
  93.                     } catch (e) {  
  94.                         reject(e);  
  95.                     }  
  96.                 });  
  97.             });  
  98.         }  
  99.     });  
  100.     return promise2;  
  101.  
  102. function resolvePromise(promise2, x, resolve, reject) {  
  103.     let self = this 
  104.     //PromiseA+ 2.3.1  
  105.     if (promise2 === x) {  
  106.         reject(new TypeError('Chaining cycle'));  
  107.     }  
  108.     if (x && typeof x === 'object' || typeof x === 'function') {  
  109.         let used; //PromiseA+2.3.3.3.3 只能調(diào)用一次  
  110.         try {  
  111.             let then = x.then;  
  112.             if (typeof then === 'function') {  
  113.                 //PromiseA+2.3.3  
  114.                 then.call(x, (y) => {  
  115.                     //PromiseA+2.3.3.1  
  116.                     if (used) return;  
  117.                     used = true 
  118.                     resolvePromise(promise2, y, resolve, reject);  
  119.                 }, (r) => {  
  120.                     //PromiseA+2.3.3.2  
  121.                     if (used) return;  
  122.                     used = true 
  123.                     reject(r);  
  124.                 });  
  125.             }else{  
  126.                 //PromiseA+2.3.3.4  
  127.                 if (used) return;  
  128.                 used = true 
  129.                 resolve(x);  
  130.             }  
  131.         } catch (e) {  
  132.             //PromiseA+ 2.3.3.2  
  133.             if (used) return;  
  134.             used = true 
  135.             reject(e);  
  136.         }  
  137.     } else {  
  138.         //PromiseA+ 2.3.3.4  
  139.         resolve(x);  
  140.     }  
  141.  
  142. module.exports = Promise

有專門的測(cè)試腳本可以測(cè)試所編寫的代碼是否符合PromiseA+的規(guī)范。

首先,在promise實(shí)現(xiàn)的代碼中,增加以下代碼: 

  1. PromisePromise.defer = Promise.deferred = function () {  
  2.     let dfd = {};  
  3.     dfd.promise = new Promise((resolve, reject) => {  
  4.         dfd.resolve = resolve;  
  5.         dfd.reject = reject;  
  6.     });  
  7.     return dfd;  

安裝測(cè)試腳本: 

  1. npm install -g promises-aplus-tests 

如果當(dāng)前的promise源碼的文件名為promise.js

那么在對(duì)應(yīng)的目錄執(zhí)行以下命令: 

  1. promises-aplus-tests promise.js 

promises-aplus-tests中共有872條測(cè)試用例。以上代碼,可以完美通過(guò)所有用例。

對(duì)上面的代碼實(shí)現(xiàn)做一點(diǎn)簡(jiǎn)要說(shuō)明(其它一些內(nèi)容注釋中已經(jīng)寫得很清楚):

  1.  onFulfilled 和 onFulfilled的調(diào)用需要放在setTimeout,因?yàn)橐?guī)范中表示: onFulfilled or onRejected must not be called until the execution context stack contains only platform code。使用setTimeout只是模擬異步,原生Promise并非是這樣實(shí)現(xiàn)的。

      2.  在 resolvePromise 的函數(shù)中,為何需要usedd這個(gè)flag,同樣是因?yàn)橐?guī)范中明確表示: If both resolvePromise and rejectPromise are called, or multiple calls to the same argument are made, the first call takes precedence, and any further calls are ignored. 因此我們需要這樣的flag來(lái)確保只會(huì)執(zhí)行一次。

      3.  self.onFulfilled 和 self.onRejected 中存儲(chǔ)了成功的回調(diào)和失敗的回調(diào),根據(jù)規(guī)范2.6顯示,當(dāng)promise從pending態(tài)改變的時(shí)候,需要按照順序去指定then對(duì)應(yīng)的回調(diào)。

PromiseA+的規(guī)范(翻譯版)

PS: 下面是我翻譯的規(guī)范,供參考

術(shù)語(yǔ)

  1.   promise 是一個(gè)有then方法的對(duì)象或者是函數(shù),行為遵循本規(guī)范
  2.   thenable 是一個(gè)有then方法的對(duì)象或者是函數(shù)
  3.   value 是promise狀態(tài)成功時(shí)的值,包括 undefined/thenable或者是 promise
  4.   exception 是一個(gè)使用throw拋出的異常值
  5.   reason 是promise狀態(tài)失敗時(shí)的值

 要求

2.1 Promise States

Promise 必須處于以下三個(gè)狀態(tài)之一: pending, fulfilled 或者是 rejected

2.1.1 如果promise在pending狀態(tài)

  1. 2.1.1.1 可以變成 fulfilled 或者是 rejected 

2.1.2 如果promise在fulfilled狀態(tài) 

  1. 2.1.2.1 不會(huì)變成其它狀態(tài)  
  2. 2.1.2.2 必須有一個(gè)value值 

2.1.3 如果promise在rejected狀態(tài) 

  1. 2.1.3.1 不會(huì)變成其它狀態(tài)  
  2. 2.1.3.2 必須有一個(gè)promise被reject的reason 

概括即是:promise的狀態(tài)只能從pending變成fulfilled,或者從pending變成rejected.promise成功,有成功的value.promise失敗的話,有失敗的原因

2.2 then方法

promise必須提供一個(gè)then方法,來(lái)訪問(wèn)最終的結(jié)果

promise的then方法接收兩個(gè)參數(shù) 

  1. promise.then(onFulfilled, onRejected) 

2.2.1 onFulfilled 和 onRejected 都是可選參數(shù) 

  1. 2.2.1.1 onFulfilled 必須是函數(shù)類型  
  2. 2.2.1.2 onRejected 必須是函數(shù)類型 

2.2.2 如果 onFulfilled 是函數(shù): 

  1. 2.2.2.1 必須在promise變成 fulfilled 時(shí),調(diào)用 onFulfilled,參數(shù)是promise的value  
  2. 2.2.2.2 在promise的狀態(tài)不是 fulfilled 之前,不能調(diào)用  
  3. 2.2.2.3 onFulfilled 只能被調(diào)用一次 

2.2.3 如果 onRejected 是函數(shù): 

  1. 2.2.3.1 必須在promise變成 rejected 時(shí),調(diào)用 onRejected,參數(shù)是promise的reason  
  2. 2.2.3.2 在promise的狀態(tài)不是 rejected 之前,不能調(diào)用  
  3. 2.2.3.3 onRejected 只能被調(diào)用一次 

2.2.4 onFulfilled 和 onRejected 應(yīng)該是微任務(wù)

2.2.5 onFulfilled  和 onRejected 必須作為函數(shù)被調(diào)用

2.2.6 then方法可能被多次調(diào)用 

  1. 2.2.6.1 如果promise變成了 fulfilled態(tài),所有的onFulfilled回調(diào)都需要按照then的順序執(zhí)行  
  2. 2.2.6.2 如果promise變成了 rejected態(tài),所有的onRejected回調(diào)都需要按照then的順序執(zhí)行 

2.2.7 then必須返回一個(gè)promise 

  1. promise2 = promise1.then(onFulfilled, onRejected);  
  2. 2.2.7.1 onFulfilled 或 onRejected 執(zhí)行的結(jié)果為x,調(diào)用 resolvePromise  
  3. 2.2.7.2 如果 onFulfilled 或者 onRejected 執(zhí)行時(shí)拋出異常e,promise2需要被reject  
  4. 2.2.7.3 如果 onFulfilled 不是一個(gè)函數(shù),promise2 以promise1的值fulfilled  
  5. 2.2.7.4 如果 onRejected 不是一個(gè)函數(shù),promise2 以promise1的reason rejected 

2.3 resolvePromise

resolvePromise(promise2, x, resolve, reject)

2.3.1 如果 promise2 和 x 相等,那么 reject promise with a TypeError

2.3.2 如果 x 是一個(gè) promsie 

  1. 2.3.2.1 如果x是pending態(tài),那么promise必須要在pending,直到 x 變成 fulfilled or rejected.  
  2. 2.3.2.2 如果 x 被 fulfilled, fulfill promise with the same value.  
  3. 2.3.2.3 如果 x 被 rejected, reject promise with the same reason. 

2.3.3 如果 x 是一個(gè) object 或者 是一個(gè) function 

  1. 2.3.3.1 let then = x.then.  
  2. 2.3.3.2 如果 x.then 這步出錯(cuò),那么 reject promise with e as the reason..  
  3. 2.3.3.3 如果 then 是一個(gè)函數(shù),then.call(x, resolvePromiseFn, rejectPromise)  
  4.     2.3.3.3.1 resolvePromiseFn 的 入?yún)⑹?nbsp;y, 執(zhí)行 resolvePromise(promise2, y, resolve, reject);  
  5.     2.3.3.3.2 rejectPromise 的 入?yún)⑹?nbsp;r, reject promise with r.  
  6.     2.3.3.3.3 如果 resolvePromise 和 rejectPromise 都調(diào)用了,那么第一個(gè)調(diào)用優(yōu)先,后面的調(diào)用忽略。  
  7.     2.3.3.3.4 如果調(diào)用then拋出異常e   
  8.         2.3.3.3.4.1 如果 resolvePromise 或 rejectPromise 已經(jīng)被調(diào)用,那么忽略  
  9.         2.3.3.3.4.3 否則,reject promise with e as the reason  
  10. 2.3.3.4 如果 then 不是一個(gè)function. fulfill promise with x. 

2.3.4 如果 x 不是一個(gè) object 或者 function,fulfill promise with x.

Promise的其他方法

雖然上述的promise源碼已經(jīng)符合PromiseA+的規(guī)范,但是原生的Promise還提供了一些其他方法,如:

  1.  Promise.resolve()
  2.  Promise.reject()
  3.  Promise.prototype.catch()
  4.  Promise.prototype.finally()
  5.  Promise.all()
  6.  Promise.race()

下面具體說(shuō)一下每個(gè)方法的實(shí)現(xiàn):

Promise.resolve

Promise.resolve(value) 返回一個(gè)以給定值解析后的Promise 對(duì)象.

  1.  如果 value 是個(gè) thenable 對(duì)象,返回的promise會(huì)“跟隨”這個(gè)thenable的對(duì)象,采用它的最終狀態(tài)
  2.  如果傳入的value本身就是promise對(duì)象,那么Promise.resolve將不做任何修改、原封不動(dòng)地返回這個(gè)promise對(duì)象。
  3.  其他情況,直接返回以該值為成功狀態(tài)的promise對(duì)象。 
  1. Promise.resolve = function (param) {  
  2.         if (param instanceof Promise) {  
  3.         return param;  
  4.     }  
  5.     return new Promise((resolve, reject) => {  
  6.         if (param && typeof param === 'object' && typeof param.then === 'function') {  
  7.             setTimeout(() => {  
  8.                 param.then(resolve, reject);  
  9.             });  
  10.         } else {  
  11.             resolve(param);  
  12.         }  
  13.     });  

thenable對(duì)象的執(zhí)行加 setTimeout的原因是根據(jù)原生Promise對(duì)象執(zhí)行的結(jié)果推斷的,如下的測(cè)試代碼,原生的執(zhí)行結(jié)果為: 20  400  30;為了同樣的執(zhí)行順序,增加了setTimeout延時(shí)。

測(cè)試代碼: 

  1. let p = Promise.resolve(20);  
  2. p.then((data) => {  
  3.     console.log(data);  
  4. });  
  5. let p2 = Promise.resolve({  
  6.     then: function(resolve, reject) {  
  7.         resolve(30);  
  8.     }  
  9. });  
  10. p2.then((data)=> {  
  11.     console.log(data)  
  12. });  
  13. let p3 = Promise.resolve(new Promise((resolve, reject) => {  
  14.     resolve(400)  
  15. }));  
  16. p3.then((data) => {  
  17.     console.log(data)  
  18. }); 

Promise.reject

Promise.reject方法和Promise.resolve不同,Promise.reject()方法的參數(shù),會(huì)原封不動(dòng)地作為reject的理由,變成后續(xù)方法的參數(shù)。 

  1. Promise.reject = function (reason) {  
  2.     return new Promise((resolve, reject) => {  
  3.         reject(reason);  
  4.     });  

Promise.prototype.catch

Promise.prototype.catch 用于指定出錯(cuò)時(shí)的回調(diào),是特殊的then方法,catch之后,可以繼續(xù) .then 

  1. Promise.prototype.catch = function (onRejected) {  
  2.     return this.then(null, onRejected);  

Promise.prototype.finally

不管成功還是失敗,都會(huì)走到finally中,并且finally之后,還可以繼續(xù)then。并且會(huì)將值原封不動(dòng)的傳遞給后面的then. 

  1. Promise.prototype.finally = function (callback) {  
  2.     return this.then((value) => {  
  3.         return Promise.resolve(callback()).then(() => {  
  4.             return value;  
  5.         });  
  6.     }, (err) => {  
  7.         return Promise.resolve(callback()).then(() => {  
  8.             throw err;  
  9.         });  
  10.     });  

Promise.all

Promise.all(promises) 返回一個(gè)promise對(duì)象

  1.  如果傳入的參數(shù)是一個(gè)空的可迭代對(duì)象,那么此promise對(duì)象回調(diào)完成(resolve),只有此情況,是同步執(zhí)行的,其它都是異步返回的。
  2.  如果傳入的參數(shù)不包含任何 promise,則返回一個(gè)異步完成.
  3.  promises 中所有的promise都promise都“完成”時(shí)或參數(shù)中不包含 promise 時(shí)回調(diào)完成。
  4.  如果參數(shù)中有一個(gè)promise失敗,那么Promise.all返回的promise對(duì)象失敗
  5.  在任何情況下,Promise.all 返回的 promise 的完成狀態(tài)的結(jié)果都是一個(gè)數(shù)組 
  1. Promise.all = function (promises) {  
  2.     promises = Array.from(promises);//將可迭代對(duì)象轉(zhuǎn)換為數(shù)組  
  3.     return new Promise((resolve, reject) => {  
  4.         let index = 0 
  5.         let result = [];  
  6.         if (promises.length === 0) {  
  7.             resolve(result);  
  8.         } else {  
  9.             function processValue(i, data) { 
  10.                  result[i] = data;  
  11.                 if (++index === promises.length) {  
  12.                     resolve(result);  
  13.                 }  
  14.             }  
  15.             for (let i = 0; i < promises.length; i++) {  
  16.                   //promises[i] 可能是普通值  
  17.                   Promise.resolve(promises[i]).then((data) => {  
  18.                     processValue(i, data);  
  19.                 }, (err) => {  
  20.                     reject(err); 
  21.                      return;  
  22.                 });  
  23.             }  
  24.         }  
  25.     });  

測(cè)試代碼: 

  1. var promise1 = new Promise((resolve, reject) => {  
  2.     resolve(3);  
  3. })  
  4. var promise2 = 42 
  5. var promise3 = new Promise(function(resolve, reject) {  
  6.   setTimeout(resolve, 100, 'foo');  
  7. });  
  8. Promise.all([promise1, promise2, promise3]).then(function(values) {  
  9.   console.log(values); //[3, 42, 'foo']  
  10. },(err)=> 
  11.     console.log(err)  
  12. });  
  13. var p = Promise.all([]); // will be immediately resolved  
  14. var p2 = Promise.all([1337, "hi"]); // non-promise values will be ignored, but the evaluation will be done asynchronously  
  15. console.log(p);  
  16. console.log(p2)  
  17. setTimeout(function(){  
  18.     console.log('the stack is now empty');  
  19.     console.log(p2);  
  20. }); 

Promise.race

Promise.race函數(shù)返回一個(gè) Promise,它將與第一個(gè)傳遞的 promise 相同的完成方式被完成。它可以是完成( resolves),也可以是失?。╮ejects),這要取決于第一個(gè)完成的方式是兩個(gè)中的哪個(gè)。

如果傳的參數(shù)數(shù)組是空,則返回的 promise 將永遠(yuǎn)等待。

如果迭代包含一個(gè)或多個(gè)非承諾值和/或已解決/拒絕的承諾,則 Promise.race 將解析為迭代中找到的第一個(gè)值。 

  1. Promise.race = function (promises) {  
  2.     promises = Array.from(promises);//將可迭代對(duì)象轉(zhuǎn)換為數(shù)組  
  3.     return new Promise((resolve, reject) => {  
  4.         if (promises.length === 0) {  
  5.             return; 
  6.          } else {  
  7.             for (let i = 0; i < promises.length; i++) {  
  8.                 Promise.resolve(promises[i]).then((data) => {  
  9.                     resolve(data);  
  10.                     return;  
  11.                 }, (err) => {  
  12.                     reject(err);  
  13.                     return;  
  14.                 });  
  15.             }  
  16.         }  
  17.     });  

測(cè)試代碼: 

  1. Promise.race([  
  2.     new Promise((resolve, reject) => { setTimeout(() => { resolve(100) }, 1000) }),  
  3.     undefined,  
  4.     new Promise((resolve, reject) => { setTimeout(() => { reject(100) }, 100) })  
  5. ]).then((data) => {  
  6.     console.log('success ', data);  
  7. }, (err) => {  
  8.     console.log('err ',err);  
  9. });  
  10. Promise.race([  
  11.     new Promise((resolve, reject) => { setTimeout(() => { resolve(100) }, 1000) }),  
  12.     new Promise((resolve, reject) => { setTimeout(() => { resolve(200) }, 200) }),  
  13.     new Promise((resolve, reject) => { setTimeout(() => { reject(100) }, 100) })  
  14. ]).then((data) => {  
  15.     console.log(data);  
  16. }, (err) => {  
  17.     console.log(err);  
  18. });  

 

責(zé)任編輯:龐桂玉 來(lái)源: 前端大全
相關(guān)推薦

2021-03-09 07:37:42

技術(shù)Promise測(cè)試

2023-09-15 15:31:23

異步編程Promise

2020-11-27 08:02:41

Promise

2021-09-02 12:07:48

Swift 監(jiān)聽(tīng)系統(tǒng)Promise

2020-12-15 08:01:24

Promise參數(shù)ES6

2018-03-13 16:04:45

Promise執(zhí)行順序

2022-01-21 08:50:15

Promise任務(wù)隊(duì)列前端

2015-07-23 11:59:27

JavascriptPromise

2020-10-23 10:10:59

Promise前端代碼

2021-04-29 08:28:24

架構(gòu)參數(shù)傳遞

2021-04-27 08:31:37

Promisereject信息

2021-04-28 08:21:21

Promise.any服務(wù)器場(chǎng)景

2016-09-18 21:14:54

JavascriptPromiseWeb

2023-10-08 10:21:11

JavaScriptAsync

2016-09-21 21:49:37

PromiseJavascript前端

2016-11-01 19:22:36

Javascript前端Promise

2017-05-11 20:20:59

JavascriptPromiseWeb

2022-09-28 12:23:36

Promise代碼

2023-01-12 11:23:11

Promise異步編程

2021-06-06 08:30:29

N-APIPromiseAPI
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)