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

資訊專欄INFORMATION COLUMN

多個(gè)請(qǐng)求并發(fā)執(zhí)行怎么寫?

gself / 3089人閱讀

摘要:最近在寫一個(gè)程序,功能是下載頁(yè)面上的資源,首先拿到頁(yè)面資源鏈接列表,如要求是資源并行下載,所有資源下載結(jié)束后通知,收集錯(cuò)誤的下載鏈接。如果把上面模擬請(qǐng)求的注釋去掉,還會(huì)發(fā)現(xiàn)是在結(jié)束后就執(zhí)行了,而后面的請(qǐng)求還未結(jié)束。

最近在寫一個(gè)Node.js程序,功能是下載頁(yè)面上的資源,首先拿到頁(yè)面資源鏈接列表,如:

[
  "https://xxx.com/img/logo.jpg",
  "https://xxx.com/img/bg.jpg",
  "https://xxx.com/css/main.css",
  "https://xxx.com/css/animate.css",
  "https://xxx.com/js/jquery.js",
  "https://xxx.com/js/form.js",
  ...
]

要求是資源并行下載,所有資源下載結(jié)束后通知收集錯(cuò)誤的下載鏈接。

如果是傳統(tǒng)做法是遍歷數(shù)組發(fā)送請(qǐng)求,聲明一個(gè)變量記錄請(qǐng)求數(shù),不管成功或失敗,結(jié)束后都給這個(gè)變量+1,并且調(diào)用一個(gè)函數(shù),這個(gè)函數(shù)判斷當(dāng)前變量是否等于數(shù)組長(zhǎng)度,相等則表示所有請(qǐng)求已經(jīng)完成。

// pseudo code
var count = 0
var errs = []
var data = [...]
function request(url) {
  ajax({url: url})
    .success(function () {
       count++
       callback()
    })
    .fail(function () {
      count++
      errs.push(...)
      callback()
    })
}

function callback() {
  if (count === data.length) {
    console.log("done!")
  }
}

data.forEach(request) 

因?yàn)檎?qǐng)求是異步的,我們也無(wú)法確定每個(gè)請(qǐng)求花費(fèi)的時(shí)間,所以只能在回調(diào)里處理?,F(xiàn)在我們有了Promise,async-await,支持同步的寫法,那可以怎么寫呢?

我們用setTimeout來(lái)模擬請(qǐng)求,數(shù)據(jù)data = [500, 400, 300, 200, 100]既是每個(gè)請(qǐng)求返回的數(shù)據(jù)也是每個(gè)請(qǐng)求所需的時(shí)間。

如果是繼發(fā)請(qǐng)求(一個(gè)請(qǐng)求結(jié)束后再請(qǐng)求后一個(gè)),那么應(yīng)該是按順序打印,理論上所有請(qǐng)求的總時(shí)間等于每個(gè)請(qǐng)求所花時(shí)間之和,約等于1500ms;如果是并發(fā)請(qǐng)求(假設(shè)請(qǐng)求數(shù)不會(huì)太多,不超過(guò)限制),順序是按時(shí)間從小到大打印,理論上所有請(qǐng)求的總時(shí)間等于最長(zhǎng)的那個(gè)時(shí)間,約等于500ms。

首先先看下怎么并行請(qǐng)求請(qǐng)求結(jié)束確定

// 模擬請(qǐng)求
function request(param) {
  return new Promise(resolve => {
    setTimeout(() => {
       console.log(param)
       resolve()
    }, param)
  })
}
const items = [500, 400, 300, 200, 100]

? 直接for循環(huán)

(() => {
  for (let item of items) {
    request(item)
  }
  console.log("end")
})()
// 輸出:end, 100, 200, 300, 400, 500

上面的輸出可以看出,請(qǐng)求是并行的,但是無(wú)法確定什么結(jié)束

? for循環(huán),使用async-await

(async () => {
  for (let item of items) {
    await request(item)
  }
  console.log("end")
})()
// 輸出:500, 400, 300, 200, 100, end

上面的代碼可以看出,雖然確定了結(jié)束,但請(qǐng)求是繼發(fā)的

? 使用Promise.all

(() => {
  Promise.all(items.map(request)).then(res => {
    console.log("end")
  })
})()
// 輸出:100, 200, 300, 400, 500, end

上面的代碼可以看出,請(qǐng)求是并發(fā)的,并且在所有請(qǐng)求結(jié)束后打印end,滿足條件

我們不能保證所有的請(qǐng)求都是正常的,接下來(lái)看看當(dāng)有請(qǐng)求出錯(cuò)時(shí)怎么處理,假設(shè)200的請(qǐng)求出錯(cuò)

function request(param) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (param === 200) {
        // console.log(param, " failed")
        return reject({
          status: "error",
          data: param
        })
      }
      // console.log(param, " success")
      resolve({
        status: "success",
        data: param
      })
    }, param)
  })
}
const items = [500, 400, 300, 200, 100]

Promisecatch方法捕獲錯(cuò)誤,最近新增的finally方法能在最后執(zhí)行

(() => {
  Promise.all(items.map(request))
    .then(res => {
      console.log(res)
    })
    .catch (err => {
      console.log(err)
    })
    .finally(res => {
      console.log("end", res)
    })
})()
// 輸出 {status: "error", data: 200}, end, undefined

上面的輸出可以看出,如果有錯(cuò)誤,則不會(huì)進(jìn)入then,而是進(jìn)入catch,然后進(jìn)入finally,但是finally不接受參數(shù),只告訴你結(jié)束了。如果把上面模擬請(qǐng)求的console.log(...)注釋去掉,還會(huì)發(fā)現(xiàn)finally是在catch結(jié)束后就執(zhí)行了,而200后面的請(qǐng)求還未結(jié)束。

接下來(lái)我們改造下模擬請(qǐng)求,在請(qǐng)求出錯(cuò)后就catch錯(cuò)誤

function request(param) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (param === 200) {
        // console.log(param, " failed")
        return reject({
          status: "error",
          data: param
        })
      }
      // console.log(param, " success")
      resolve({
        status: "success",
        data: param
      })
    }, param)
  }).catch(err => err)
}

(() => {
  Promise.all(items.map(request))
    .then(res => {
      console.log(res, "end")
    })
})()
// 輸出 [{…}, {…}, {…}, {stauts: "error", data: 200}, {…}], end

這樣就可以在then中拿到全部的結(jié)果了,如果要用for循環(huán)的話也是可以的

(async () => {
  const temp = []
  // 這個(gè)for循環(huán)的作用和上面的map類似
  for (let item of items) {
    temp.push(request(item))
  }

  const result = []
  for (let t of temp) {
    result.push(await t)
  }
  console.log(result, "end")
})()
// 輸出與上面一致

第一個(gè)for循環(huán)保證并發(fā)請(qǐng)求,保存了Promise,第二個(gè)循環(huán)加入await保證按順序執(zhí)行。

好了,以上就是全部?jī)?nèi)容,你有更好的寫法嗎?

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

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

相關(guān)文章

  • 非常硬核的技術(shù)知識(shí)-CopyOnWrite思想

    摘要:而且只要他更新完畢對(duì)修飾的變量賦值,那么讀線程立馬可以看到最新修改后的數(shù)組,這是保證的。這個(gè)時(shí)候,就采用了思想來(lái)實(shí)現(xiàn)這個(gè),避免更新的時(shí)候阻塞住高頻的讀操作,實(shí)現(xiàn)無(wú)鎖的效果,優(yōu)化線程并發(fā)的性能。 今天聊一個(gè)非常硬核的技術(shù)知識(shí),給大家分析一下CopyOnWrite思想是什么,以及在Java并發(fā)包中的具體體現(xiàn),包括在Kafka內(nèi)核源碼中是如何運(yùn)用這個(gè)思想來(lái)優(yōu)化并發(fā)性能的。這個(gè)CopyOnW...

    amc 評(píng)論0 收藏0
  • MySQL數(shù)據(jù)庫(kù)優(yōu)化

    摘要:具體來(lái)說(shuō),就是在寫數(shù)據(jù)庫(kù)的時(shí)候同時(shí)寫一份數(shù)據(jù)到緩存集群里,然后用緩存集群來(lái)承載大部分的讀請(qǐng)求。各種精妙的架構(gòu)設(shè)計(jì)因此一篇小文頂多具有拋磚引玉的效果但是數(shù)據(jù)庫(kù)優(yōu)化的思想差不多就這些了 前言 數(shù)據(jù)庫(kù)優(yōu)化一方面是找出系統(tǒng)的瓶頸,提高M(jìn)ySQL數(shù)據(jù)庫(kù)的整體性能,而另一方面需要合理的結(jié)構(gòu)設(shè)計(jì)和參數(shù)調(diào)整,以提高用戶的相應(yīng)速度,同時(shí)還要盡可能的節(jié)約系統(tǒng)資源,以便讓系統(tǒng)提供更大的負(fù)荷. 1. 優(yōu)化一覽...

    wangshijun 評(píng)論0 收藏0
  • 史上最全阿里 Java 面試題總結(jié)

    摘要:以下為大家整理了阿里巴巴史上最全的面試題,涉及大量面試知識(shí)點(diǎn)和相關(guān)試題。的內(nèi)存結(jié)構(gòu),和比例。多線程多線程的幾種實(shí)現(xiàn)方式,什么是線程安全。點(diǎn)擊這里有一套答案版的多線程試題。線上系統(tǒng)突然變得異常緩慢,你如何查找問(wèn)題。 以下為大家整理了阿里巴巴史上最全的 Java 面試題,涉及大量 Java 面試知識(shí)點(diǎn)和相關(guān)試題。 JAVA基礎(chǔ) JAVA中的幾種基本數(shù)據(jù)類型是什么,各自占用多少字節(jié)。 S...

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

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

0條評(píng)論

gself

|高級(jí)講師

TA的文章

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