91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

JavaScript異步解決方案有哪些

發布時間:2023-05-06 09:46:37 來源:億速云 閱讀:149 作者:iii 欄目:開發技術

這篇文章主要介紹“JavaScript異步解決方案有哪些”,在日常操作中,相信很多人在JavaScript異步解決方案有哪些問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”JavaScript異步解決方案有哪些”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

1.回調

回調簡單地理解為一個函數作為參數傳遞給另一個函數,回調是早期最常用的異步解決方案之一。

回調不一定是異步的,也不直接相關。

舉個簡單的例子:

function f1(cb) {
  setTimeout(() => {
    cb && cb();
  }, 2000);
}
 
f1(() => {
  console.log("1");
});

如上,我們在函數f1中使用setTimeout模擬一個耗時2s的任務,在耗時任務結束時拋出回調,這樣我們就可以調用它,讓回調函數在耗時結束時執行函數 f1 中的任務。

這樣,我們就把同步操作變成了異步操作。f1不會阻塞程序,相當于先執行程序的主要邏輯,推遲執行耗時操作。

回調的優點和缺點

優點:簡單,容易理解。

缺點:代碼不優雅,可讀性差,不易維護,耦合度高,層層嵌套造成回調地獄。

2.事件監聽(發布訂閱模式)

發布-訂閱模式定義了對象之間一對多的依賴關系,這樣當一個對象的狀態發生變化時,所有依賴它的對象都會得到通知。

我們都使用過發布-訂閱模式,例如,如果我們將事件函數綁定到 DOM 節點。

document.body.addEventListener('click', function () {
  console.log('click');
})

但這只是發布-訂閱模式最簡單的使用,在很多場景下我們往往會使用一些自定義事件來滿足我們的需求。

有很多方法可以實現發布-訂閱模式,所以這里有一個使用類的簡單實現。

class Emitter {
  constructor() {
    // _listener array, key is the custom event name, value is the execution callback array - as there may be more than one
    this._listener = []
  }
 
  // 訂閱 監聽事件
  on(type, fn) {
    // Determine if the event exists in the _listener array.
    // Exists to push the callback to the value array corresponding to the event name, does not exist to add directly
    this._listener[type] 
      ? this._listener[type].push(fn) 
     : (this._listener[type] = [fn])
  }
 
  // Publish Trigger Event
  trigger(type, ...rest) {
    // Determine if the trigger event exists
    if (!this._listener[type]) return
    // Iterate through the array of callbacks executing the event and pass the parameters
    this._listener[type].forEach(callback => callback(...rest))
  }
}

如上所示,我們創建了一個 Emitter 類,并在和觸發器上添加了兩個原型方法,使用如下。

// Create an emitter instance
const emitter = new Emitter()
 
emitter.on("done", function(arg1, arg2) {
  console.log(arg1, arg2)
})
 
emitter.on("done", function(arg1, arg2) {
  console.log(arg2, arg1)
})
 
function fn1() {
  console.log('I am the main program')
  setTimeout(() => {
    emitter.trigger("done", "Asynchronous parameter I", "Asynchronous parameter II")
  }, 1000)
}
 
fn1()

我們先創建一個emitter實例,然后注冊事件,然后觸發事件,這樣也解決了異步問題。

事件監聽的優點和缺點

優點:更符合模塊化思想,我們在編寫自己的監聽器的時候可以做很多優化,從而更好的監聽程序的運行。

缺點:整個程序變成了事件驅動,或多或少影響了流程,而且每次使用都要注冊事件監聽器然后觸發,比較麻煩,代碼也不是很優雅。

3.Promise

ES6 標準化并引入了 Promise 對象,這是一種異步編程的解決方案。

簡單的說,就是用同步的方式寫異步代碼,可以用來解決回調地獄問題。

Promise對象的狀態一旦改變,就不會再改變,只有兩種可能的改變。

  1. 由待定改為已解決。

  2. 由Pending改為Rejected。

我們使用 setTimeout 來模擬異步操作。

function analogAsync(n) {
  return new Promise((resolve) => {
    setTimeout(() => resolve(n + 500), n);
  });
}
 
function fn1(n) {
  console.log(`step1 with ${n}`);
  return analogAsync(n);
}
 
function fn2(n) {
  console.log(`step2 with ${n}`);
  return analogAsync(n);
}
 
function fn3(n) {
  console.log(`step3 with ${n}`);
  return analogAsync(n);
}

使用 Promise 來實現。

function fn() {
  let time1 = 0;
  fn1(time1)
    .then((time2) => fn2(time2))
    .then((time3) => fn3(time3))
    .then((res) => {
      console.log(`result is ${res}`);
    });
}
 
fn();

Promise 優點和缺點

優點:Promise以同步的方式編寫異步代碼,避免了回調函數層層嵌套,可讀性更強。鏈式操作,可以在then中繼續寫Promise對象并return,然后繼續調用then進行回調操作。

缺點:Promise對象一旦創建就會立即執行,不能中途取消。如果沒有設置回調函數,Promise 會在內部拋出錯誤,不會向外流。

4.Generator

Generator其實就是一個函數,只不過是一個特殊的函數。Generator 的特別之處在于它可以中途停止。

function *generatorFn() {
  console.log("a");
  yield '1';
  console.log("b");
  yield '2'; 
  console.log("c");
  return '3';
}
 
let it = generatorFn();
it.next();
it.next();
it.next();
it.next();

上面的示例是一個具有以下特征的生成器函數。與普通函數不同,Generator 函數在函數之后和函數名稱之前有一個 *,該函數有一個內部 yield 字段,函數調用后的返回值使用next方法。

Generator的優點和缺點

優點:優雅的流程控制方法,允許函數被中斷地執行。

缺點:Generator函數的執行必須依賴executor,對于只做異步處理還是不太方便。

5.async/await

ES2017標準引入了async函數,使得異步操作更加方便。async是異步的意思,await是async wait的簡寫,也就是異步等待。async/await 被許多人認為是 js 中異步操作的終極和最優雅的解決方案。

異步在做什么?

async 函數返回一個 Promise 對象。如果直接在 async 函數中返回一個直接量,async 會通過 Promise.resolve() 將直接量包裝在一個 Promise 對象中。

await 是什么?

await 是一個表達式,其計算結果為 Promise 對象或其他值(換句話說,沒有特殊限定,無論如何)。

如果 await 后面沒有跟 Promise 對象,則直接執行。

如果 await 后面跟著一個 Promise 對象,它會阻塞后面的代碼,Promise 對象解析,然后獲取 resolve 的值作為 await 表達式的結果。

await 只能在異步函數中使用

上面使用setTimeout來模擬異步操作,我們使用async/await來實現。

async function fn() {
  let time1 = 0;
  let time2 = await fn1(time1);
  let time3 = await fn2(time2);
  let res = await fn3(time3);
  console.log(`result is ${res}`);
}
 
fn();

輸出結果和上面的 Promise 實現是一樣的,但是 async/await 的代碼結構看起來更清晰,幾乎和同步寫法一樣優雅。

async/await的優點和缺點

優點:內置執行器,語義更好,適用性更廣。

缺點:誤用 await 可能會導致性能問題,因為 await 會阻塞代碼。

到此,關于“JavaScript異步解決方案有哪些”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

墨脱县| 山丹县| 民勤县| 清水县| 奉贤区| 盐城市| 河西区| 台中市| 泸西县| 陆川县| 盐边县| 南汇区| 阿克陶县| 龙门县| 南城县| 大兴区| 神农架林区| 自贡市| 苏尼特左旗| 青海省| 赣榆县| 隆昌县| 金塔县| 广河县| 固阳县| 岱山县| 砀山县| 新沂市| 新郑市| 祁阳县| 竹溪县| 宿迁市| 扶余县| 集贤县| 南宫市| 伽师县| 北流市| 哈尔滨市| 鲜城| 保山市| 朝阳市|