国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

多個請求并發(fā)執(zhí)行怎么寫?

gself / 3046人閱讀

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

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

[
  "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",
  ...
]

要求是資源并行下載所有資源下載結束后通知收集錯誤的下載鏈接

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

// 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) 

因為請求是異步的,我們也無法確定每個請求花費的時間,所以只能在回調里處理。現(xiàn)在我們有了Promiseasync-await,支持同步的寫法,那可以怎么寫呢?

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

如果是繼發(fā)請求(一個請求結束后再請求后一個),那么應該是按順序打印,理論上所有請求的總時間等于每個請求所花時間之和,約等于1500ms;如果是并發(fā)請求(假設請求數(shù)不會太多,不超過限制),順序是按時間從小到大打印,理論上所有請求的總時間等于最長的那個時間,約等于500ms

首先先看下怎么并行請求請求結束確定

// 模擬請求
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

上面的輸出可以看出,請求是并行的,但是無法確定什么結束

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

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

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

? 使用Promise.all

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

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

我們不能保證所有的請求都是正常的,接下來看看當有請求出錯時怎么處理,假設200的請求出錯

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方法捕獲錯誤,最近新增的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

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

接下來我們改造下模擬請求,在請求出錯后就catch錯誤

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中拿到全部的結果了,如果要用for循環(huán)的話也是可以的

(async () => {
  const temp = []
  // 這個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")
})()
// 輸出與上面一致

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

好了,以上就是全部內容,你有更好的寫法嗎?

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

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/106106.html

相關文章

  • 非常硬核的技術知識-CopyOnWrite思想

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

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

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

    wangshijun 評論0 收藏0
  • 史上最全阿里 Java 面試題總結

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

    winterdawn 評論0 收藏0

發(fā)表評論

0條評論

gself

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<