国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

js中如何順序執(zhí)行異步任務(wù)

這篇具有很好參考價(jià)值的文章主要介紹了js中如何順序執(zhí)行異步任務(wù)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

在js中,任務(wù)可分為兩種,同步任務(wù)和異步任務(wù)。

(1) 同步任務(wù)

又叫 非耗時(shí)任務(wù),指的是在主線程排隊(duì)執(zhí)行的那些任務(wù)
只有前一個(gè)任務(wù)執(zhí)行完畢,才能執(zhí)行后一個(gè)任務(wù)

(2) 異步任務(wù)

又叫 耗時(shí)任務(wù),異步任務(wù)由JavaScript委托給宿主環(huán)境進(jìn)行執(zhí)行
當(dāng)異步任務(wù)執(zhí)行完成后,會(huì)通知JavaScript主線程執(zhí)行異步任務(wù)的回調(diào)函數(shù)
當(dāng)我們打開網(wǎng)站時(shí),像圖片的加載,音樂的加載,其實(shí)就是一個(gè)異步任務(wù)

現(xiàn)有a、b和c三個(gè)任務(wù),如果其為同步任務(wù),可以很簡(jiǎn)單地順序執(zhí)行,但如果其為異步任務(wù),該如何順序執(zhí)行呢?

一、回調(diào)函數(shù)

function thing(thingName, callback) {
   
    setTimeout(() => {
   
        console.log(`執(zhí)行${
     thingName}任務(wù)`)
        typeof callback === 'function' && callback()
    }, 1000)
}

// 執(zhí)行a任務(wù)
// 執(zhí)行b任務(wù)
// 執(zhí)行c任務(wù)
thing('a', () => {
   
    thing('b', () => {
   
        thing('c')
    })
})

優(yōu)點(diǎn):簡(jiǎn)單、方便、實(shí)用

缺點(diǎn):回調(diào)函數(shù)層層嵌套,不易于閱讀和維護(hù),形成回調(diào)地獄。

二、promise

1. 使用方式

基本使用

new Promise ((resolve, reject) => {
   
  // 執(zhí)行代碼
}).then(() => {
   
  // 期約兌現(xiàn)
}).catch(() => {
   
  // 期約拒絕
})

詳細(xì)使用戳這里

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise#%E7%A4%BA%E4%BE%8B

2. 異步任務(wù)順序執(zhí)行

function thing(thingName) {
   
    return new Promise(resolve => {
   
        setTimeout(() => {
   
            console.log(`執(zhí)行${
     thingName}任務(wù)`)
            resolve()
        }, 1000)
    })
}

// 執(zhí)行a任務(wù)
// 執(zhí)行b任務(wù)
// 執(zhí)行c任務(wù)
thing('a')
    .then(() => thing('b'))
    .then(() => thing('c'))

3. 實(shí)現(xiàn)原理

那么如何實(shí)現(xiàn)一個(gè)promise呢?實(shí)現(xiàn)promise之前,先分析下promise的結(jié)構(gòu)

  1. promise存在三個(gè)狀態(tài),pending 待定, fulfilled 兌現(xiàn), rejected 拒絕,因此需要

    (1)定義三個(gè)常量 PENDING、FULFILLED、REJECTED 對(duì)應(yīng)三種狀態(tài)

    (2)定義 status 表示期約當(dāng)前狀態(tài)

    (3)定義 value 表示已兌現(xiàn)期約值、定義 reason 表示已拒絕期約原因

  2. 在調(diào)用promise的實(shí)例函數(shù)時(shí),我們傳入了一個(gè)執(zhí)行器,執(zhí)行器接收兩個(gè)函數(shù),其作用分別為將待定期約轉(zhuǎn)化為已兌現(xiàn)期約與已拒絕期約。因此需要定義兩個(gè)函數(shù) resolve reject

  3. 已兌現(xiàn)期約、已拒絕期約處理函數(shù) then

    已拒絕期約處理函數(shù) catch

    最終執(zhí)行函數(shù) finally

  4. 靜態(tài)函數(shù) resolve、reject、 all race 的實(shí)現(xiàn)

代碼實(shí)現(xiàn)基于以下鏈接調(diào)整

https://juejin.cn/post/6945319439772434469#heading-30

3.1 promise簡(jiǎn)易實(shí)現(xiàn)
// MyPromise.js

const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'

class MyPromise {
   
  // 期約狀態(tài), 初始值為pending
  status = PENDING
  // 已兌現(xiàn)期約值
  value = null
  // 已拒絕期約原因
  reason = null

  constructor(executor){
   
    executor(this.resolve, this.reject)
  }

  // 將待定期約轉(zhuǎn)化為已兌現(xiàn)期約
  resolve = (value) => {
   
    if (this.status === PENDING) {
   
      this.status = FULFILLED
      this.value = value
    }
  }

  // 將待定期約轉(zhuǎn)化為已拒絕期約
  reject = (reason) => {
   
    if (this.status === PENDING) {
   
      this.status = REJECTED
      this.reason = reason
    }
  }

  then (onFulfilled, onRejected) {
   
    if (this.status === FULFILLED) {
   
      onFulfilled(this.value)
    } else if (this.status === REJECTED) {
   
      onRejected(this.reason)
    }
  }
}

module.exports = MyPromise

同目錄下新建 test.js 文件用于測(cè)試

// test.js

// 引入我們的 MyPromise.js
const MyPromise = require('./MyPromise')
const promise1 = new MyPromise((resolve, reject) => {
   
   resolve('resolve')
})

const promise2 = new MyPromise((resolve, reject) => {
   
    reject('reject')
})

promise1.then(value => {
   
  console.log('promise1 then', value)
}, reason => {
   
  console.log('promise1 catch', reason)
})

promise2.then(value => {
   
    console.log('promise2 then', value)
  }, reason => {
   
    console.log('promise2 catch', reason)
  })

// 執(zhí)行結(jié)果
// promise1 then resolve
// promise2 catch reject
3.2 加入異步邏輯

繼續(xù)測(cè)試,發(fā)現(xiàn)異步執(zhí)行resolve函數(shù)時(shí),會(huì)存在問題。因此,我們需對(duì)異步邏輯進(jìn)行處理。

// test.js

const MyPromise = require('./MyPromise')
const promise = new MyPromise((resolve, reject) => {
   
   setTimeout(() => resolve('resolve'), 0)
})

promise.then(value => {
   
    console.log('promise then', value)
  }, reason => {
   
    console.log('promise catch', reason)
  })

// 期望輸出 promise then resolve
// 實(shí)際無輸出

(1) 緩存兌現(xiàn)與拒絕回調(diào)

// 存儲(chǔ)兌現(xiàn)回調(diào)函數(shù)
onFulfilledCallback = null
// 存儲(chǔ)拒絕回調(diào)函數(shù)
onRejectedCallback = null

(2) then 方法中新增待定期約處理

then (onFulfilled, onRejected) {
   
  if (this.status === FULFILLED) {
   
    onFulfilled(this.value)
  } else if (this.status === REJECTED) {
   
    onRejected(this.reason)
  }  else if (this.status === PENDING) {
   
    this.onFulfilledCallback = onFulfilled
    this.onRejectedCallback = onRejected
  }
}

(3) resolve 與 reject 中調(diào)用回調(diào)函數(shù)

  // 將待定期約轉(zhuǎn)化為已兌現(xiàn)期約
  resolve = (value) => {
   
    if (this.status === PENDING) {
   
      this.status = FULFILLED
      this.value = value
      // 兌現(xiàn)回調(diào)函數(shù)存在則執(zhí)行
      this.onFulfilledCallback && this.onFulfilledCallback(value)
    }
  }

  // 將待定期約轉(zhuǎn)化為已拒絕期約
  reject = (reason) => {
   
    if (this.status === PENDING) {
   
      this.status = REJECTED
      this.reason = reason
      // 拒絕回調(diào)函數(shù)存在則執(zhí)行
      this.onRejectedCallback && this.onRejectedCallback(reason)
    }
  }

使用以下代碼再次驗(yàn)證,異步問題解決。

// test.js

const MyPromise = require('./MyPromise')
const promise = new MyPromise((resolve, reject) => {
   
   setTimeout(() => resolve('resolve'), 0)
})

promise.then(value => {
   
    console.log('promise then', value)
  }, reason => {
   
    console.log('promise catch', reason)
  })

// 執(zhí)行結(jié)果: promise then resolve
3.3 實(shí)現(xiàn) then 方法多次調(diào)用添加多個(gè)處理函數(shù)

Promise支持添加多個(gè)處理函數(shù),來測(cè)試下自定義Promise是否滿足。

// test.js

const MyPromise = require('./MyPromise')
const promise = new MyPromise((resolve, reject) => {
   
  setTimeout(() => {
   
    resolve('success')
  }, 2000) 
})

promise.then(value => {
   
  console.log(1)
  console.log('resolve', value)
})
 
promise.then(value => {
   
  console.log(2)
  console.log('resolve', value)
})

promise.then(value => {
   
  console.log(3)
  console.log('resolve', value)
})

// 3
// resolve success

經(jīng)測(cè)試,自定義Promise并不能添加多個(gè)處理函數(shù),繼續(xù)修改。

(1) 新增兌現(xiàn)與拒絕回調(diào)數(shù)組

// 存儲(chǔ)兌現(xiàn)回調(diào)函數(shù)數(shù)組
onFulfilledCallbacks = []
// 存儲(chǔ)拒絕回調(diào)函數(shù)數(shù)組
onRejectedCallbacks = []

(2) then方法中存儲(chǔ)回調(diào)

then (onFulfilled, onRejected) {
   
  if (this.status === FULFILLED) {
   
    onFulfilled(this.value)
  } else if (this.status === REJECTED) {
   
    onRejected(this.reason)
  }  else if (this.status === PENDING) {
   
    this.onFulfilledCallbacks.push(onFulfilled)
    this.onRejectedCallbacks.push(onRejected)
  }
}

(3) resolve 與 reject 中循環(huán)調(diào)用回調(diào)函數(shù)文章來源地址http://www.zghlxwxcb.cn/news/detail-489142.html

// 將待定期約轉(zhuǎn)化為已兌現(xiàn)期約
resolve = (value) => {
   
  if (this.status === PENDING) {
   
    this.status = FULFILLED
    this.value = value
    // 兌現(xiàn)回調(diào)函數(shù)存在則執(zhí)行
    while (this.onFulfilledCallbacks.length) {
   

到了這里,關(guān)于js中如何順序執(zhí)行異步任務(wù)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 宏任務(wù)與微任務(wù)執(zhí)行順序及對(duì)比記錄

    宏任務(wù)與微任務(wù)執(zhí)行順序及對(duì)比記錄

    目錄 前言 一、 宏任務(wù)、微任務(wù)的基本概念 1.宏任務(wù)介紹 2.微任務(wù)介紹 3.宏任務(wù)、微任務(wù)發(fā)展及出現(xiàn)的原因: ?4.宏任務(wù)、微任務(wù)的基本類型 二、?事件循環(huán)模型(Event Loop) 三、 Promise、async和await 在事件循環(huán)中的處理 1.Promise: ????????2. async/await : 這個(gè)知識(shí)點(diǎn)比較容易忽

    2024年01月21日
    瀏覽(22)
  • 【案例講解】LVGL 向UI任務(wù)發(fā)送順序執(zhí)行的延時(shí)任務(wù)方法

    更多源碼分析請(qǐng)?jiān)L問: LVGL 源碼分析大全 由于 lv_timer_create 的執(zhí)行實(shí)現(xiàn)方式為 后進(jìn)先出 的棧執(zhí)行方式,這導(dǎo)致在添加一些需要順序執(zhí)行的延時(shí)任務(wù)時(shí)會(huì)很麻煩,因此,需要實(shí)現(xiàn)一個(gè) 先進(jìn)先出 接口。 以ESP32中 examples/factory_demo 為例:ESP32上的LVGL是采用多任務(wù)(相當(dāng)于Linux上的

    2024年01月16日
    瀏覽(26)
  • 使用多線程執(zhí)行任務(wù),并獲取返回結(jié)果,附異步實(shí)現(xiàn)

    使用多線程執(zhí)行任務(wù),并獲取返回結(jié)果,附異步實(shí)現(xiàn)

    這里創(chuàng)建了一個(gè)包含三個(gè)線程的固定線程池 線程池的介紹 根據(jù)主機(jī)情況實(shí)現(xiàn)自定義線程池: 也可以通過繼承 ThreadPoolExecutor 類來實(shí)現(xiàn)一個(gè)自定義線程池工具類。ThreadPoolExecutor 是 Java 標(biāo)準(zhǔn)庫(kù)中提供的一個(gè)線程池實(shí)現(xiàn),通過繼承它,我們可以實(shí)現(xiàn)自定義的線程池。 下面是一個(gè)繼

    2024年02月16日
    瀏覽(15)
  • Flutter實(shí)現(xiàn)ControlExecutor進(jìn)行多個(gè)異步任務(wù)執(zhí)行時(shí)監(jiān)聽狀態(tài)并可指定最后執(zhí)行的異步并在指定的異步執(zhí)行完畢后結(jié)束executor并回調(diào)。

    Flutter實(shí)現(xiàn)ControlExecutor進(jìn)行多個(gè)異步任務(wù)執(zhí)行時(shí)監(jiān)聽狀態(tài)并可指定最后執(zhí)行的異步并在指定的異步執(zhí)行完畢后結(jié)束executor并回調(diào)。

    1.場(chǎng)景 當(dāng)有多個(gè)接口請(qǐng)求時(shí),且接口調(diào)用不是同時(shí)進(jìn)行時(shí),而且接口調(diào)用有可能時(shí)鏈?zhǔn)降模虚g也有可能加入別的邏輯,但是需要在第一個(gè)接口調(diào)用時(shí)打開等待框,在最后一個(gè)接口調(diào)用完成時(shí)關(guān)閉等待框類似需求時(shí),可以用到ControlExecutor進(jìn)行接口執(zhí)行過程的監(jiān)聽,并可標(biāo)記最

    2024年02月09日
    瀏覽(14)
  • 20230515學(xué)習(xí)筆記——js中的同步任務(wù)與異步任務(wù),宏任務(wù)與微任務(wù)

    20230515學(xué)習(xí)筆記——js中的同步任務(wù)與異步任務(wù),宏任務(wù)與微任務(wù)

    2023-05-15 (1)js中的同步任務(wù)與異步任務(wù) ①同步任務(wù)是指:不耗時(shí)的任務(wù),就是執(zhí)行很快, ②異步任務(wù)是指:耗時(shí)的任務(wù),它里面有一個(gè)機(jī)制是EventLoop(事件循環(huán)),即值耗時(shí)任務(wù)會(huì)被js分配到宿主環(huán)境中進(jìn)行執(zhí)行,執(zhí)行后的結(jié)果放到一個(gè)“消息隊(duì)列”中,當(dāng)js將同步任務(wù)執(zhí)行完

    2024年02月04日
    瀏覽(20)
  • JS執(zhí)行機(jī)制--同步與異步

    JS執(zhí)行機(jī)制--同步與異步

    單線程 JavaScript語(yǔ)言具有單線程的特點(diǎn),同一個(gè)時(shí)間只能做一件事情。這是因?yàn)镴avaScript腳本語(yǔ)言是為了處理頁(yè)面中用戶的交互,以及操作DOM而誕生的。如果對(duì)某個(gè)DOM元素進(jìn)行添加和刪除,不同同時(shí)進(jìn)行。應(yīng)該是先添加,再刪除,事件有序。 單線程的特點(diǎn)是所有任務(wù)都需要排隊(duì)

    2023年04月20日
    瀏覽(19)
  • js執(zhí)行順序

    js執(zhí)行順序

    1.首先js是單線程的 所有的同步任務(wù)都是按順序依次執(zhí)行的,前面的執(zhí)行完了之后才會(huì)執(zhí)行后面的任務(wù)。遇到計(jì)算量大的代碼就會(huì)阻塞在這里。下面的代碼就是打印輸出10000次,當(dāng)循環(huán)走完了之后 才會(huì)走后面的代碼,輸出的時(shí)間是981ms 輸出981ms 2.因?yàn)閖s是單線程的,所有的任務(wù)

    2023年04月08日
    瀏覽(17)
  • 一文讀懂異步和同步——async/await在運(yùn)行時(shí)和普通代碼的執(zhí)行順序的問題

    一文讀懂異步和同步——async/await在運(yùn)行時(shí)和普通代碼的執(zhí)行順序的問題

    一、執(zhí)行順序問題 JavaScript中的await語(yǔ)句是異步編程中用于等待Promise對(duì)象執(zhí)行結(jié)果的,它通常與async函數(shù)一起使用。在使用await時(shí),程序的執(zhí)行將暫停,直到該后面的Promise對(duì)象完成執(zhí)行并返回結(jié)果。 函數(shù)代碼執(zhí)行順序通常情況下按照代碼所在文件從上至下

    2024年02月03日
    瀏覽(20)
  • Django 如何使用 Celery 完成異步任務(wù)或定時(shí)任務(wù)

    以前版本的 Celery 需要一個(gè)單獨(dú)的庫(kù)(django-celery)才能與 Django 一起工作, 但從 Celery 3.1 開始,情況便不再如此,我們可以直接通過 Celery 庫(kù)來完成在 Django 中的任務(wù)。 以 Docker 安裝為例,安裝一個(gè)密碼為 mypassword 的 Redis 服務(wù)端 在 Django 項(xiàng)目中創(chuàng)建一個(gè) celery.py 文件,并配置

    2023年04月25日
    瀏覽(18)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包