狠狠色丁香婷婷综合尤物/久久精品综合一区二区三区/中国有色金属学报/国产日韩欧美在线观看 - 国产一区二区三区四区五区tv

LOGO OA教程 ERP教程 模切知識交流 PMS教程 CRM教程 開發文檔 其他文檔  
 
網站管理員

【JavaScript】掌握異步編程,看這里!

admin
2024年3月29日 23:43 本文熱度 623

異步處理的概念

JavaScript 中的異步處理指的是在代碼執行過程中,能夠不阻塞當前線程并處理一些時間較長的操作。異步處理通常涉及到回調函數、Promise、async/await 等機制。

在 JavaScript 中,傳統的同步處理方式采用的是阻塞式的單線程模型。這種模型的缺點是當一個任務被執行時,它會一直執行到結束,期間如果有耗時的操作也會一直阻塞下去,直到任務執行完畢,才會執行后續的任務。這種方式會導致頁面卡死,體驗非常不好。

因此,JavaScript 異步處理機制應運而生,它允許在代碼執行過程中,執行一些耗時的操作,而不會阻塞當前線程。

回調函數

回調函數是一種很常見的異步編程模型,通過在異步操作完成后調用回調函數來通知異步操作已結束,從而執行后續的任務。例如:

function fetchData(callback) {

  setTimeout(function() {

const data = { name: '張三', age: 20 };

    callback(data);

  }, 1000);

}


fetchData(function(data) {

  console.log(data);

});

在這個示例中,fetchData() 函數在完成數據加載后,調用回調函數 callback() 并傳遞數據作為參數。當數據加載完成后,控制器會跳轉到回調函數中執行后續任務。

Promise

Promise 是一種比較流行的異步編程模型,它可以在異步操作完成后執行一些回調操作,并將結果返回給請求方。Promise 代表了一個異步操作的最終完成(或失敗)及其結果值。例如:

function fetchData() {

  return new Promise(function(resolve, reject) {

    setTimeout(function() {

      const data = { name: '張三', age: 20 };

      resolve(data);

    }, 1000);

  });

}


fetchData().then(function(data) {

  console.log(data);

});

異步處理常見場景與處理策略

異步處理常見場景包括但不限于:

  1. 網絡請求:當請求數據需要一定的時間才能返回時,為了避免用戶體驗受到影響,需要進行異步處理。
  2. 定時任務:定時執行任務,需要進行異步處理。
  3. 事件處理:通過異步處理來避免事件處理函數執行時間過長,導致頁面卡頓等問題。

  4. 大量數據處理:對于大量數據的處理,需要進行異步處理,以免阻塞主線程。

JavaScript 引擎是單線程執行的,也就是說同一時間內只有一個任務在執行。當需要進行異步操作時,通常會使用回調函數。

假設我們有一個獲取用戶信息的異步函數 getUserInfo,在信息獲取完成后需要調用相關回調函數。一種實現方式是將回調函數作為 getUserInfo 函數的第二個參數傳入,信息獲取完成后調用該函數。

function getUserInfo(userId, callback) {

  setTimeout(function() {

    const userInfo = {

      id: userId,

      name: "Tom",

      age: 25

    }

    callback(userInfo)

  }, 1000)

}


getUserInfo(1001, function(userInfo) {

  console.log(userInfo)

})

上述代碼首先調用 getUserInfo 函數,該函數通過 setTimeout 模擬異步操作,等待 1 秒鐘后獲取用戶信息,并在信息獲取完成后調用傳入的回調函數。最后在回調函數中輸出用戶信息。

Promise A+ 規范

Promise 的狀態

一個 Promise 的當前狀態必須為以下三種狀態中的一種:等待態(Pending)執行態(Fulfilled)和 拒絕態(Rejected)

  • 等待態(Pending)處于等待態時,promise 需滿足以下條件:

    • 可以遷移至執行態或拒絕態(fulfill、reject)

  • 執行態(Fulfilled)處于執行態時,promise 需滿足以下條件:

    • 不能遷移至其他任何狀態

    • 必須擁有一個不可變的終值

  • 拒絕態(Rejected)處于拒絕態時,promise 需滿足以下條件:

    • 不能遷移至其他任何狀態

    • 必須擁有一個不可變的原因

    • 這里的不可變指的是恒等(即可用 === 判斷相等),而不是意味著更深層次的不可變(譯者注:概指當 value 或 reason 不是基本值時,只要求其引用地址相等,但屬性值可被更改)。


      面試官文檔 Promise A+ 規范時,首先要提出的便是三個態:pending、fulfilled、rejected


一個 promise 必須提供一個 then 方法以訪問其當前值、終值和據因。

promise 的 then 方法接受兩個參數:

promise.then(onFulfilled, onRejected);

其中,onFulfilled 和 onRejected 都是可選參數。

  • 如果 onFulfilled 不是函數,其必須被忽略

  • 如果 onRejected 不是函數,其必須被忽略

發布-訂閱模式

根據 Promise A+ 規范,每次 then 返回的值也需要滿足 thenable,也就是說我們需要將 resolve 返回值使用 promise 包裹,在本例中就是需要將返回值包裝為新的 HePromise 對象。開發之前我們不妨先來看看 Promise 鏈式調用的示例:

const p = new Promise(resolve => resolve(1));

p.then(r1 => {

console.log(r1);

return 2;

})

  .then(r2 => {

console.log(r2);

return 3;

  })

  .then(r3 => {

console.log(r3);

  });

實現all方法

就是將傳入數組中的值 promise 化,然后保證每個任務都處理后,最終 resolve。示例如下:

class HePromise {

static all(promises: any[]) {

let index = 0;

const result: any[] = [];

const pLen = promises.length;

return new HePromise((resolve, reject) => {

      promises.forEach(p => {

        HePromise.resolve(p).then(

val => {

            index++;

            result.push(val);

if (index === pLen) {

              resolve(result);

            }

          },

err => {

if (reject) reject(err);

          },

        );

      });

    });

  }

}

編寫測試用例如下:

it('HePromise.all', done => {

  HePromise.all([1, 2, 3]).then(res => {

    expect(res).toEqual([1, 2, 3]);

    done();

  });

});

執行測試,測試通過。

實現race方法

就是將傳入數組中的值 promise 化,只要其中一個任務完成,即可 resolve。示例如下:

class HePromise {

static race(promises: any[]): HePromise {

return new HePromise((resolve, reject) => {

      promises.forEach(p => {

        HePromise.resolve(p).then(

val => {

            resolve(val);

          },

err => {

if (reject) reject(err);

          },

        );

      });

    });

  }

}

編寫測試用例:

it('HePromise.race', done => {

  HePromise.race([11, 22, 33]).then(res => {

    expect(res).toBe(11);

    done();

  });

});

執行測試,測試通過。

整體測試代碼情況如下:

async 與 await 用法及原理詳解

async function test() {

    const res = await Promise.resolve(1)

    return res

}

需要注意的是,使用 async、await 處理異步操作時,需要注意異常的處理。

異常處理

通常我們使用 try、catch 捕獲 async、await 執行過程中拋出的異常,就像這樣:

async function test() {

    let res = null

    try {

        const res = await Promise.resolve(1)

        return res

    } catch(e) {

        console.log(e)

    }

}

從零實現一個類似 async、await 的函數

promise+generator

function fn(nums) {

    return new Promise(resolve = >{

        setTimeout(() = >{

            resolve(nums * 2)

        },

        1000)

    })

}

function * gen() {

    const num1 = yield fn(1)

    const num2 = yield fn(num1)

    const num3 = yield fn(num2)

    return num3

}

function generatorToAsync(generatorFn) {

    return function() {

        return new Promise((resolve, reject) = >{

            const g = generatorFn() const next1 = g.next() next1.value.then(res1 = >{


                const next2 = g.next(res1) // 傳入上次的res1

                next2.value.then(res2 = >{


                    const next3 = g.next(res2) // 傳入上次的res2

                    next3.value.then(res3 = >{


                        // 傳入上次的res3

                        resolve(g.next(res3).value)

                    })

                })

            })

        })

    }

}


const asyncFn = generatorToAsync(gen)

asyncFn().then(res = >console.log(res)) // 3秒后輸出 8

自動執行

自動執行其實就是運用遞歸,將生成器函數產生的數據不斷調用 next,直至執行完成。

function getData(endpoint) {

  return new Promise(resolve => {

    setTimeout(() => {

      resolve(`Data received from ${endpoint}`)

    }, 2000)

  })

}


// 生成器函數

function* getDataAsync() {

  const result1 = yield getData('Endpoint 1')

  console.log(result1)

  const result2 = yield getData('Endpoint 2')

  console.log(result2)

  return 'All data received'

}


// 將生成器函數包裝成 Promise

function asyncToPromise(generatorFn) {

  const generator = generatorFn()


  function handleResult(result) {

    if (result.done) {

      return Promise.resolve(result.value)

    }


    return Promise.resolve(result.value)

      .then(res => handleResult(generator.next(res)))

      .catch(err => handleResult(generator.throw(err)))

  }


  try {

    return handleResult(generator.next())

  } catch (error) {

    return Promise.reject(error)

  }

}


asyncToPromise(getDataAsync).then(result => console.log(result))

總結

這里介紹了回調函數、Promise、async/await 等機制。其中涉及到JavaScript事件循環機制沒有展開分析,后續會總結相應的通關手冊。 


該文章在 2024/3/29 23:46:43 編輯過
關鍵字查詢
相關文章
正在查詢...
點晴ERP是一款針對中小制造業的專業生產管理軟件系統,系統成熟度和易用性得到了國內大量中小企業的青睞。
點晴PMS碼頭管理系統主要針對港口碼頭集裝箱與散貨日常運作、調度、堆場、車隊、財務費用、相關報表等業務管理,結合碼頭的業務特點,圍繞調度、堆場作業而開發的。集技術的先進性、管理的有效性于一體,是物流碼頭及其他港口類企業的高效ERP管理信息系統。
點晴WMS倉儲管理系統提供了貨物產品管理,銷售管理,采購管理,倉儲管理,倉庫管理,保質期管理,貨位管理,庫位管理,生產管理,WMS管理系統,標簽打印,條形碼,二維碼管理,批號管理軟件。
點晴免費OA是一款軟件和通用服務都免費,不限功能、不限時間、不限用戶的免費OA協同辦公管理系統。
Copyright 2010-2025 ClickSun All Rights Reserved