<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      [JS] promise知識點與應用場景

      Promise是JS中用于處理異步操作的方法,- 支持鏈式調用從而解決了地獄回調問題。

      Promise的基礎用法

      狀態

      promise有三種狀態:

      • Pending(待定):初始狀態,既不是成功也不是失敗。
      • Fulfilled(已成功):操作成功完成。
      • Rejected(已失敗):操作失敗。
      const promise = new Promise((resolve, reject) => {
        // 異步操作
        if (成功) {
          resolve(value);
        } else {
          reject(error);
        }
      });
      
      

      實例方法

      Promise有三個實例方法,分別是thencatch,和finally

      • then用于處理Promise成功的情況:
      promise.then((value) => {
        console.log(value);
      });
      
      • catch用于處理Promise失敗的情況,即異常捕獲:
      promise.catch((error) => {
        console.error(error);
      });
      
      • finally:無論Promise最終狀態如何(成功或失敗),都會執行finally中的回調。
      promise.finally(() => {
        console.log('操作完成');
      });
      

      鏈式調用

      then方法可以返回一個Promise,并在后續鏈式地繼續調用then方法。

      doSomething()
        .then((result) => {
          return doSomethingElse(result);
        })
        .then((newResult) => {
          return doThirdThing(newResult);
        })
        .then((finalResult) => {
          console.log(`Final result: ${finalResult}`);
        })
        .catch((error) => {
          console.error(error);
        });
      

      鏈式調用只需要在尾部調用一次catch,在鏈式調用的過程中發生的異常都會被這個尾部的catch捕獲。

      靜態方法

      • Promise.resolve(value):返回一個成功的Promise,值為value;常見于后面跟上then方法將一個函數推入微任務隊列;
      • Promise.reject(reason):返回一個失敗的Promise,原因為reason
      • Promise.all(iterable):并行執行多個Promise,所有Promise都成功時返回一個包含所有結果的新Promise,如果有任何一個失敗,則返回失敗的Promise。
      Promise.all([promise1, promise2, promise3])
        .then((values) => console.log(values))
        .catch((error) => console.error(error));
      
      • Promise.race(iterable):返回第一個完成的Promise,無論成功還是失敗。
      Promise.race([promise1, promise2, promise3])
        .then((value) => console.log(value))
        .catch((error) => console.error(error));
      

      Promise.all的應用場景

      并發請求,有時候在一個頁面中需要使用多個GET請求獲取頁面數據并渲染,并且這些GET請求沒有依賴關系,即不需要考慮請求順序。那么這時就可以使用Promise.all并發執行這些GET請求。

      const fetchUser = fetch('https://api.example.com/user');
      const fetchPosts = fetch('https://api.example.com/posts');
      const fetchComments = fetch('https://api.example.com/comments');
      
      Promise.all([fetchUser, fetchPosts, fetchComments])
        .then(([userResponse, postsResponse, commentsResponse]) => {
          return Promise.all([userResponse.json(), postsResponse.json(), commentsResponse.json()]);
        })
        .then(([userData, postsData, commentsData]) => {
          console.log(userData, postsData, commentsData);
        })
        .catch((error) => {
          console.error('請求失敗', error);
        });
      

      并發執行需要注意并發量不要太大,我們可以通過實現一個并發控制的類來限制并發量。

      class RequestScheduler {
        constructor(concurrencyLimit) {
          this.concurrencyLimit = concurrencyLimit;
          this.running = 0;
          this.queue = [];
        }
      
        // 添加請求到隊列
        add(requestFn) {
          return new Promise((resolve, reject) => {
            this.queue.push({ requestFn, resolve, reject });
            this.runNext();
          });
        }
      
        // 執行下一個請求
        runNext() {
          if (this.running >= this.concurrencyLimit || this.queue.length === 0) {
            return;
          }
      
          const { requestFn, resolve, reject } = this.queue.shift();
          this.running++;
      
          requestFn()
            .then((result) => {
              resolve(result);
            })
            .catch((error) => {
              reject(error);
            })
            .finally(() => {
              this.running--;
              this.runNext();
            });
        }
      }
      
      // 使用示例
      const scheduler = new RequestScheduler(3); // 限制并發請求數量為3
      
      const createRequest = (url) => () => fetch(url).then((response) => response.json());
      
      const urls = [
        'https://jsonplaceholder.typicode.com/posts/1',
        'https://jsonplaceholder.typicode.com/posts/2',
        'https://jsonplaceholder.typicode.com/posts/3',
        'https://jsonplaceholder.typicode.com/posts/4',
        'https://jsonplaceholder.typicode.com/posts/5'
      ];
      
      const requestPromises = urls.map((url) => scheduler.add(createRequest(url)));
      
      Promise.all(requestPromises)
        .then((results) => {
          console.log('所有請求完成:', results);
        })
        .catch((error) => {
          console.error('請求失敗:', error);
        });
      
      • createRequest方法生成返回Promise的請求函數;
      • scheduler.add方法將一個請求添加到調度器中,并在并發限制允許的情況下執行;
      • Promise.all的作用是等待所有請求完成,并且統一處理異常。

      Promise.race的應用場景

      Promise.race方法關注的是最快出結果(不管是fulfilled還是rejected)的promise,可以實現超時處理。
      超時處理:在race中傳入網絡請求的promise和定時器的promise,如果網絡請求在指定時間內到達則正常執行then流程,如果定時器先到達則表示超時,調用reject走catch流程。

      const fetchWithTimeout = (url, timeout) => {
        const fetchPromise = fetch(url);
        const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error('請求超時')), timeout));
        return Promise.race([fetchPromise, timeoutPromise]);
      };
      
      fetchWithTimeout('https://api.example.com/data', 5000)
        .then((response) => response.json())
        .then((data) => {
          console.log('請求成功', data);
        })
        .catch((error) => {
          console.error('請求失敗或超時', error);
        });
      

      Promise.allSettled

      Promise.allSettled 方法返回一個在所有給定的 Promise 已經 fulfilled 或 rejected 后的 Promise,并且帶有一個對象數組,每個對象表示對應的 Promise 結果。
      如果是fulfilled,則結果字段為value
      如果是rejected,則結果字段為reason

      const promises = [
        Promise.resolve('resolved'),
        Promise.reject('rejected'),
        new Promise((resolve) => setTimeout(resolve, 1000, 'pending resolved'))
      ];
      
      Promise.allSettled(promises)
        .then((results) => {
          results.forEach((result) => console.log(result));
        });
      
      // 輸出:
      // { status: 'fulfilled', value: 'resolved' }
      // { status: 'rejected', reason: 'rejected' }
      // { status: 'fulfilled', value: 'pending resolved' }
      

      Promise.any

      接受一個promise數組,返回一個promise。
      和Promise.race不同,Promise.any會過濾掉所有rejected 的promise,而關注第一個fulfilled的promise的值。
      如果數組中所有promise都被rejected的話,那么會返回一個AggregateError類型的實例,帶有errors字段,是一個數組,指明了每一個promise的reason
      應用場景:any可以用來在多個備用資源中獲取最先成功響應的資源。
      最快成功返回的備用資源:假設一個數據有多個可用來源,我們只需要拿到其中一個成功響應就可以了,那么肯定是想要拿最快返回的那一個,這個時候用any就很nice~

      const loadImage = (url) => new Promise((resolve, reject) => {
        const img = new Image();
        img.onload = () => resolve(url);
        img.onerror = () => reject(new Error(`Failed to load image at ${url}`));
        img.src = url;
      });
      
      const imageUrls = ['image1.png', 'image2.png', 'image3.png'];
      const imagePromises = imageUrls.map(loadImage);
      
      Promise.any(imagePromises)
        .then((result) => {
          console.log('第一個加載完成的圖片', result);
        })
        .catch((error) => {
          console.error('所有圖片加載失敗', error);
        });
      

      Promise.withResolvers

      這個方法返回一個新的promise對象和用于解決或拒絕它的resolvereject方法。
      可以簡單地使用Promise手動實現:

      Promise.withResolvers = function() {
        let resolve, reject;
        const promise = new Promise((res, rej) => {
          resolve = res;
          reject = rej;
        });
        return { promise, resolve, reject };
      };
      

      使用 Promise.withResolvers() 關鍵的區別在于解決和拒絕函數現在與 Promise 本身處于同一作用域,而不是在執行器中被創建和一次性使用。
      通常在一些重復事件中使用,例如在處理流數據或者隊列的時候,在這些場景下通常可以減少嵌套,優化代碼結構。
      這里介紹MDN上面的案例:將流轉換為異步可迭代對象。

      // 定義 async generator 函數 readableToAsyncIterable,將流轉換為異步可迭代對象
      async function* readableToAsyncIterable(stream) {
        // 創建 Promise 和解析器對象
        let { promise, resolve, reject } = Promise.withResolvers();
      
        // 監聽流的錯誤事件,一旦出錯則調用 reject 方法
        stream.on("error", (error) => reject(error));
      
        // 監聽流的結束事件,一旦結束則調用 resolve 方法
        stream.on("end", () => resolve());
      
        // 監聽流的可讀事件,一旦流準備好可以讀取則調用 resolve 方法
        stream.on("readable", () => resolve());
      
        // 循環處理流中的數據塊,直到流不再可讀
        while (stream.readable) {
          // 等待當前的 Promise 解決
          await promise;
      
          let chunk;
          // 循環讀取流中的數據塊
          while ((chunk = stream.read())) {
            // 生成數據塊
            yield chunk;
          }
      
          // 獲取新的 Promise 和解析器對象,以便下一輪循環使用
          ({ promise, resolve, reject } = Promise.withResolvers());
        }
      }
      

      創建一個簡單的可讀流測試一下:

      const { Readable } = require('stream');
      
      // 測試函數
      async function testReadableToAsyncIterable() {
        // 創建一個簡單的可讀流
        const data = ['Hello', 'World'];
        const readableStream = Readable.from(data);
      
        // 將可讀流轉換為異步可迭代對象
        const asyncIterable = readableToAsyncIterable(readableStream);
      
        // 使用 for await...of 循環遍歷異步可迭代對象中的數據塊,并驗證結果
        let result = '';
        for await (const chunk of asyncIterable) {
          result += chunk.toString();
        }
      
        // 斷言結果是否符合預期
        if (result === data.join('')) {
          console.log('測試通過:數據正常讀取和處理。');
        } else {
          console.error('測試失敗:數據讀取和處理出現問題。');
        }
      }
      
      // 執行測試函數
      testReadableToAsyncIterable();
      

      Promise規范與手寫Promise

      ?? Promises/A+ 規范
      示例代碼:

      const PENDING = 'pending';
      const FULFILLED = 'fulfilled';
      const REJECTED = 'rejected';
      
      class MyPromise {
        constructor(executor) {
          this.state = PENDING; // 初始狀態為 pending
          this.value = undefined; // 成功時的值
          this.reason = undefined; // 失敗時的原因
          this.onFulfilledCallbacks = []; // 存儲成功時的回調函數
          this.onRejectedCallbacks = []; // 存儲失敗時的回調函數
      
          // 定義 resolve 函數,用于將狀態轉變為 fulfilled,并執行成功的回調函數
          const resolve = (value) => {
            if (this.state === PENDING) {
              this.state = FULFILLED;
              this.value = value;
              // 執行所有成功回調函數
              this._executeCallbacks(this.onFulfilledCallbacks, this.value);
            }
          };
      
          // 定義 reject 函數,用于將狀態轉變為 rejected,并執行失敗的回調函數
          const reject = (reason) => {
            if (this.state === PENDING) {
              this.state = REJECTED;
              this.reason = reason;
              // 執行所有失敗回調函數
              this._executeCallbacks(this.onRejectedCallbacks, this.reason);
            }
          };
      
          try {
            // 執行執行器函數,并傳入 resolve 和 reject 函數
            executor(resolve, reject);
          } catch (error) {
            // 如果執行器函數拋出異常,則直接 reject
            reject(error);
          }
        }
      
        // 定義 then 方法,用于鏈式調用
        then(onFulfilled, onRejected) {
          return new MyPromise((resolve, reject) => {
            // 定義處理成功的函數
            const handleFulfilled = (value) => {
              try {
                // 如果 onFulfilled 存在,則執行它,并獲取結果
                const result = onFulfilled ? onFulfilled(value) : value;
                this._handleResult(result, resolve, reject);
              } catch (error) {
                reject(error);
              }
            };
      
            // 定義處理失敗的函數
            const handleRejected = (reason) => {
              try {
                // 如果 onRejected 存在,則執行它,并獲取結果
                const result = onRejected ? onRejected(reason) : reason;
                this._handleResult(result, resolve, reject);
              } catch (error) {
                reject(error);
              }
            };
      
            // 根據當前 Promise 的狀態執行不同的邏輯
            if (this.state === FULFILLED) {
              // 使用 queueMicrotask 來模擬微任務,確保在當前事件循環結束后執行 handleFulfilled
              queueMicrotask(() => handleFulfilled(this.value));
            } else if (this.state === REJECTED) {
              // 使用 queueMicrotask 來模擬微任務,確保在當前事件循環結束后執行 handleRejected
              queueMicrotask(() => handleRejected(this.reason));
            } else if (this.state === PENDING) {
              // 如果當前狀態仍為 pending,則將處理成功和失敗的函數加入對應的回調數組中
              this.onFulfilledCallbacks.push(value => {
                queueMicrotask(() => handleFulfilled(value));
              });
              this.onRejectedCallbacks.push(reason => {
                queueMicrotask(() => handleRejected(reason));
              });
            }
          });
        }
      
        // 定義 catch 方法,用于捕獲 Promise 鏈中的錯誤
        catch(onRejected) {
          return this.then(null, onRejected);
        }
      
        // 靜態方法 resolve,返回一個立即 resolved 的 Promise 對象
        static resolve(value) {
          return new MyPromise((resolve) => {
            resolve(value);
          });
        }
      
        // 靜態方法 reject,返回一個立即 rejected 的 Promise 對象
        static reject(reason) {
          return new MyPromise((resolve, reject) => {
            reject(reason);
          });
        }
      
        // 靜態方法 all,接收一個 Promise 數組,返回一個新的 Promise,當所有 Promise 都成功時才成功,結果為一個值數組
        static all(promises) {
          return new MyPromise((resolve, reject) => {
            const results = [];
            let count = 0;
      
            promises.forEach((promise, index) => {
              promise.then((value) => {
                results[index] = value;
                count++;
                // 當所有 Promise 都成功時,resolve 結果數組
                if (count === promises.length) {
                  resolve(results);
                }
              }).catch(reject); // 一旦有 Promise 失敗,則整體 Promise 也失敗
            });
          });
        }
      
        // 靜態方法 race,接收一個 Promise 數組,返回一個新的 Promise,以最先 resolved 或 rejected 的 Promise 的結果作為結果
        static race(promises) {
          return new MyPromise((resolve, reject) => {
            // 遍歷 Promise 數組,一旦有 Promise 解決或拒絕,則立即 resolve 或 reject
            promises.forEach((promise) => {
              promise.then(resolve).catch(reject);
            });
          });
        }
      
        // 私有方法,用于處理 then 方法返回的結果
        _handleResult(result, resolve, reject) {
          if (result instanceof MyPromise) {
            // 如果返回結果是一個 Promise 實例,則繼續鏈式調用
            result.then(resolve, reject);
          } else {
            // 否則直接將結果傳遞給下一個 Promise 的 resolve
            resolve(result);
          }
        }
      
        // 私有方法,用于執行回調函數數組中的所有回調
        _executeCallbacks(callbacks, arg) {
          callbacks.forEach(callback => {
            // 使用 queueMicrotask 來模擬微任務,確保在當前事件循環結束后執行回調
            queueMicrotask(() => callback(arg));
          });
        }
      }
      

      為什么使用數組存儲回調函數?
      通常我們在使用promise的時候只會調用一次then方法并傳入一個回調函數,但其實then方法是可以多次調用的,例如下面這段代碼,則會添加多個回調,因此需要使用數組存儲回調函數。

      const promise = new Promise((resolve, reject) => {
        // 執行異步操作
        setTimeout(() => {
          resolve('成功'); // 改變狀態為 fulfilled
        }, 1000);
      });
      
      promise.then(
        value => console.log('成功處理1:', value),
        reason => console.error('失敗處理1:', reason)
      );
      
      promise.then(
        value => console.log('成功處理2:', value),
        reason => console.error('失敗處理2:', reason)
      );
      
      posted @ 2024-07-05 19:06  feixianxing  閱讀(417)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 少妇人妻偷人精品系列| 四虎库影成人在线播放| 中文字幕av无码免费一区| 内射合集对白在线| 中文国产不卡一区二区| 国产精品无码免费播放| 精品无码人妻| 精品视频一区二区福利午夜| 国产精品欧美一区二区三区不卡| 无码抽搐高潮喷水流白浆| 中文字幕免费不卡二区| 午夜DY888国产精品影院| 欧美激情 亚洲 在线| 五月天中文字幕mv在线| 国产成人av一区二区三| 性色在线视频精品| 男女动态无遮挡动态图| 一区二区三区在线 | 欧洲 | 欧美日韩高清在线观看| 狠狠色噜噜狠狠狠狠2021| 国产精品老熟女免费视频| 欧美亚洲综合成人a∨在线| 91精品91久久久久久| av色蜜桃一区二区三区| 亚洲亚洲人成综合网络| 亚洲综合色婷婷中文字幕| 石原莉奈日韩一区二区三区| 亚洲国产成人AⅤ片在线观看| 无码激情亚洲一区| 色爱区综合激情五月激情| 国产欧美在线观看一区| 亚洲精品一区国产精品| 亚洲国产精品成人综合色| 最新精品国偷自产在线| 亚洲欧洲日产国码久在线| 久久国内精品自在自线观看| 国产精品原创不卡在线| 亚洲成av人片天堂网无码| 日韩成人性视频在线观看| 欧美成人精品三级网站视频| 亚洲av无码一区二区三区网站 |