亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

異步請(qǐng)求回調(diào)嵌套解決方案

Winer / 2185人閱讀

摘要:前言在前端異步請(qǐng)求中,要獲取數(shù)據(jù),傳統(tǒng)的寫(xiě)法是回調(diào),但這種方法不利于代碼的維護(hù)和可讀性,所以時(shí)代通過(guò)和解決了這種問(wèn)題,更是通過(guò)和使其更加簡(jiǎn)潔通過(guò)替代回調(diào)嵌套的特點(diǎn)是初始化后,調(diào)用一次方法會(huì)暫停在關(guān)鍵字前,同時(shí)也可以在方法里傳值,使對(duì)應(yīng)的語(yǔ)句

前言

在前端異步請(qǐng)求中,要獲取數(shù)據(jù),傳統(tǒng)的寫(xiě)法是ajax回調(diào),但這種方法
不利于代碼的維護(hù)和可讀性,所以es6時(shí)代通過(guò)Generator和Promise解決了這種問(wèn)題,es7更是通過(guò)async和await使其更加簡(jiǎn)潔

通過(guò)Generator替代回調(diào)嵌套
Generator的特點(diǎn)是初始化后,調(diào)用一次next方法會(huì)暫停在yield關(guān)鍵字前,同時(shí)也可以在next方法里傳值,使對(duì)應(yīng)的yield語(yǔ)句獲取到

首先編寫(xiě)準(zhǔn)備代碼

const axios = require("axios")

const http = axios.create({
  baseURL: "http://127.0.0.1:89",
  timeout: 3000,
  headers: {"Accept": "application/json"}
});


let it;

定義的it是迭代器的意思,現(xiàn)在還沒(méi)有值

異步請(qǐng)求調(diào)用方法

function call(url,options={}) {
    setTimeout(()=>{
        if ( !it ) {
            throw new Error("請(qǐng)初始化生成器")
        }
        http(url,options)
        .then(v=>{
            
            it.next(v.data)  // 生成器傳遞參數(shù),并且啟動(dòng)下一次執(zhí)行
        })
    },0)
}

setTimeout包裹,是確保這段代碼是異步執(zhí)行,如果不加,同步執(zhí)行的it判斷可能會(huì)拋出異常

編寫(xiě)生成器,這里是主要的異步請(qǐng)求邏輯處理

/**
    多個(gè)請(qǐng)求互相依賴
    1. 根據(jù)用戶名,密碼獲取用戶憑證
    2. 根據(jù)用戶憑證獲取用戶數(shù)據(jù)id列表
    3. 獲取數(shù)據(jù)列表中第一條數(shù)據(jù)詳情
*/
function * getData() {
    const data1 = yield call("/login", { method: "POST", data: JSON.stringify({user:"root",pass:"123456"}) })
    console.log("我是結(jié)果1:",data1)
    const data2 = yield call("/list", { method: "POST", headers: { token: data1.data.token } })
    console.log("我是結(jié)果2:",data2)
    const data3 = yield call("/item", { method: "POST", headers: { token: data1.data.token }, data: JSON.stringify({ id:data2.data.ids[0] }) })
    console.log("我是結(jié)果3:",data3)  
}

調(diào)用,運(yùn)行

it = getData()
it.next()

這里給it附上值,然后會(huì)觸發(fā)第2步的代碼

運(yùn)行流程

首先我們定義了生成器,運(yùn)行它的時(shí)候,只需執(zhí)行it.netx,然后會(huì)運(yùn)行第一個(gè)yield后面的語(yǔ)句,并停在第一個(gè)yield語(yǔ)句處,當(dāng)call函數(shù)里的異步請(qǐng)求執(zhí)行完畢,會(huì)將異步請(qǐng)求的結(jié)果it.next(data)傳遞給第一個(gè)yield前面的取值語(yǔ)句,然后會(huì)執(zhí)行到第二個(gè)yield語(yǔ)句后面的call,以此類推,直到整個(gè)生成器執(zhí)行完畢

Generator + Promise

單個(gè)通過(guò)Generator已經(jīng)可以解決大部分異步嵌套的問(wèn)題,但是不夠完善,要確保it初始化,必須讓整個(gè)call異步執(zhí)行,代碼不夠優(yōu)雅,而且依賴外部it,結(jié)構(gòu)分散,所以我們用Generator + Promise可以進(jìn)一步完善

簡(jiǎn)化call方法

function call(url,options={}) {
  return http(url,options)
}

去掉在call里執(zhí)行it.next

增加外部調(diào)用生成器next函數(shù)run

function run (g) {
  const it = g();  // 初始化生成器, 注意這里的冒號(hào)
  
  (function each(res) {
      // 根據(jù)生成器的返回結(jié)果進(jìn)行判斷
      if (!res.done && res.value instanceof Promise ) {  // 如果是Promise返回
          res.value.then(v=>{
              each( it.next(v.data) )    // 這里是方案一的call里的next并傳值到下一次next 
          })
      } else if (res.done) {    // 生成器執(zhí)行結(jié)束, 運(yùn)行結(jié)束
          return
      } else {
          throw new Error("yield 后面請(qǐng)用返回Promise的函數(shù)")
      }
  })(it.next())    //自運(yùn)行
}

運(yùn)行

run(getData)

運(yùn)行方法一中的getData生成器,得到的結(jié)果一樣

getData里yield后的函數(shù)擴(kuò)展

根據(jù)run函數(shù)可知,只要it.next返回的結(jié)果是Promise即可正常運(yùn)行,那么在getData里如下寫(xiě)法也是可以的

function * getData() {
  const data1 = yield http("/login", { method: "POST", data: JSON.stringify({user:"root",pass:"123456"}) })
  console.log("我是結(jié)果1:",data1)
  const data2 = yield http("/list", { method: "POST", headers: { token: data1.data.token } })
  console.log("我是結(jié)果2:",data2)
  const data3 = yield http("/item", { method: "POST", headers: { token: data1.data.token }, data: JSON.stringify({ id:data2.data.ids[0] }) })
  console.log("我是結(jié)果3:",data3)  
}

**這里的http函數(shù)是axios的一個(gè)實(shí)例,返回值為Promise,
外層加call是可以在call里寫(xiě)一些異常,或者測(cè)試處理,類似Reactdva處理方式**

ES7處理方式

如果你覺(jué)得方案二還是有些繁瑣,那么可以試試ES7的await語(yǔ)法

改造getData函數(shù)如下

/**
    多個(gè)請(qǐng)求互相依賴
    1. 根據(jù)用戶名,密碼獲取用戶憑證
    2. 根據(jù)用戶憑證獲取用戶數(shù)據(jù)id列表
    3. 獲取數(shù)據(jù)列表中第一條數(shù)據(jù)詳情
*/
async function getData() {
    const { data:data1 } = await call("/login", { method: "POST", data: JSON.stringify({user:"root",pass:"123456"}) })
    console.log("我是結(jié)果1:",data1)
    const { data:data2 } = await call("/list", { method: "POST", headers: { token: data1.data.token } })
    console.log("我是結(jié)果2:",data2)
    const { data:data3 } = await call("/item", { method: "POST", headers: { token: data1.data.token }, data: JSON.stringify({ id:data2.data.ids[0] }) })
    console.log("我是結(jié)果3:",data3)  
}

和方案二比較這個(gè)方法頭部多了async關(guān)鍵字,去掉了*號(hào),yield換成了await,這是ES7異步函數(shù)的聲明方式。
注意返回值不是通過(guò)方案二中next res.data注入,所以獲取到的是整個(gè)res,取值的時(shí)候注意拿結(jié)果里的.data數(shù)據(jù)

運(yùn)行

getData()

結(jié)果和方案一二一樣,這種方式更加簡(jiǎn)潔易懂

方案三簡(jiǎn)單完整代碼

個(gè)人比較喜歡簡(jiǎn)潔有效的代碼,所以推薦方案三

const axios = require("axios")

const http = axios.create({
  baseURL: "http://127.0.0.1:89",
  timeout: 3000,
  headers: {"Accept": "application/json"}
});


/**
    多個(gè)請(qǐng)求互相依賴
    1. 根據(jù)用戶名,密碼獲取用戶憑證
    2. 根據(jù)用戶憑證獲取用戶數(shù)據(jù)id列表
    3. 獲取數(shù)據(jù)列表中第一條數(shù)據(jù)詳情
*/
async function getData() {
    const { data:data1 } = await http("/login", { method: "POST", data: JSON.stringify({user:"root",pass:"123456"}) })
    console.log("我是結(jié)果1:",data1)
    const { data:data2 } = await http("/list", { method: "POST", headers: { token: data1.data.token } })
    console.log("我是結(jié)果2:",data2)
    const { data:data3 } = await http("/item", { method: "POST", headers: { token: data1.data.token }, data: JSON.stringify({ id:data2.data.ids[0] }) })
    console.log("我是結(jié)果3:",data3)  
}

getData() //運(yùn)行

以上代碼僅完成了核心功能,一些防御性和異常處理不完善,僅供理解和學(xué)習(xí)

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/106585.html

相關(guān)文章

  • javascript異步中的回調(diào)

    摘要:如果你把函數(shù)的指針地址作為參數(shù)傳遞給另一個(gè)函數(shù),當(dāng)這個(gè)指針被用來(lái)調(diào)用其所指向的函數(shù)時(shí),我們就說(shuō)這是回調(diào)函數(shù)?;卣{(diào)函數(shù)不是由該函數(shù)的實(shí)現(xiàn)方直接調(diào)用,而是在特定的事件或條件發(fā)生時(shí)由另外的一方調(diào)用的,用于對(duì)該事件或條件進(jìn)行響應(yīng)。 同期異步系列文章推薦談一談javascript異步j(luò)avascript異步與promisejavascript異步之Promise.all()、Promise.ra...

    WalkerXu 評(píng)論0 收藏0
  • Promise到底解決了什么問(wèn)題?

    摘要:我的博客大家都知道解決了回調(diào)地獄的問(wèn)題。這就是異步的嵌套帶來(lái)的可讀性的問(wèn)題,它是由異步的運(yùn)行機(jī)制引起的。在與第三方團(tuán)隊(duì)溝通之后問(wèn)題得到了解決。這不但使代碼變得臃腫不堪,還進(jìn)一步加劇了可讀性的問(wèn)題。的特征保證了可以解決信任問(wèn)題。 我的github博客 https://github.com/zhuanyongxigua/blog 大家都知道Promise解決了回調(diào)地獄的問(wèn)題。說(shuō)到回調(diào)地獄,...

    yibinnn 評(píng)論0 收藏0
  • 從源碼看 Promise 概念與實(shí)現(xiàn)

    摘要:從源碼看概念與實(shí)現(xiàn)是異步編程中的重要概念,它較好地解決了異步任務(wù)中回調(diào)嵌套的問(wèn)題。這些概念中有趣的地方在于,標(biāo)識(shí)狀態(tài)的變量如都是形容詞,用于傳入數(shù)據(jù)的接口如與都是動(dòng)詞,而用于傳入回調(diào)函數(shù)的接口如及則在語(yǔ)義上用于修飾動(dòng)詞的副詞。 從源碼看 Promise 概念與實(shí)現(xiàn) Promise 是 JS 異步編程中的重要概念,它較好地解決了異步任務(wù)中回調(diào)嵌套的問(wèn)題。在沒(méi)有引入新的語(yǔ)言機(jī)制的前提下,這...

    kel 評(píng)論0 收藏0
  • 【筆記】 你不知道的JS讀書(shū)筆記——異步

    摘要:異步請(qǐng)求線程在在連接后是通過(guò)瀏覽器新開(kāi)一個(gè)線程請(qǐng)求將檢測(cè)到狀態(tài)變更時(shí),如果設(shè)置有回調(diào)函數(shù),異步線程就產(chǎn)生狀態(tài)變更事件,將這個(gè)回調(diào)再放入事件循環(huán)隊(duì)列中。 基礎(chǔ):瀏覽器 -- 多進(jìn)程,每個(gè)tab頁(yè)獨(dú)立一個(gè)瀏覽器渲染進(jìn)程(瀏覽器內(nèi)核) 每個(gè)瀏覽器渲染進(jìn)程是多線程的,主要包括:GUI渲染線程 JS引擎線程 也稱為JS內(nèi)核,負(fù)責(zé)處理Javascript腳本程序。(例如V8引擎) JS引擎線程負(fù)...

    junnplus 評(píng)論0 收藏0
  • Promise學(xué)習(xí)總結(jié)

    摘要:引擎線程也稱為內(nèi)核,負(fù)責(zé)處理腳本程序例如引擎引擎線程負(fù)責(zé)解析腳本,運(yùn)行代碼。對(duì)象代表一個(gè)未完成但預(yù)計(jì)將來(lái)會(huì)完成的操作。注意一旦新建就會(huì)立即執(zhí)行它屬于,無(wú)法取消。 寫(xiě)在前面: 第一遍學(xué)Promise時(shí), 只是大概過(guò)了一遍, 感覺(jué)學(xué)的不夠深入, 這一篇算是對(duì)之前的一個(gè)總結(jié)吧. Promise在ES6中也屬于一個(gè)較難理解的一部分; 所以在學(xué)習(xí)一個(gè)比較難理解的知識(shí)點(diǎn)時(shí), 我們可以圍繞這個(gè)知識(shí)點(diǎn)...

    twohappy 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<