鴻蒙(HarmonyOS)性能優(yōu)化實(shí)戰(zhàn)-文件上傳下載性能提升

概述

在開(kāi)發(fā)應(yīng)用時(shí)率触,要實(shí)現(xiàn)高效的客戶端跟服務(wù)器之間數(shù)據(jù)交換终议,文件傳輸?shù)男阅苁侵陵P(guān)重要的。一個(gè)數(shù)據(jù)交換性能較低的應(yīng)用會(huì)導(dǎo)致其在加載過(guò)程中耗費(fèi)較長(zhǎng)時(shí)間葱蝗,在很多的場(chǎng)景造成頁(yè)面卡頓穴张,極大的影響了用戶體驗(yàn)。相反两曼,一個(gè)數(shù)據(jù)交換高效的應(yīng)用皂甘,則會(huì)讓應(yīng)用變得更加流暢。

本文將介紹兩種常見(jiàn)的上傳下載傳輸和網(wǎng)絡(luò)請(qǐng)求的關(guān)鍵技術(shù):數(shù)據(jù)壓縮和斷點(diǎn)續(xù)傳悼凑,可提升上傳下載的性能偿枕、減少寬帶占用,從而提高數(shù)據(jù)傳輸效率户辫。

上傳下載接口

目前系統(tǒng)內(nèi)提供給文件上傳下載可用的模塊有@ohos.net.http模塊和@ohos.request模塊渐夸。@ohos.net.http模塊提供基礎(chǔ)的HTTP數(shù)據(jù)請(qǐng)求能力,功能較為基礎(chǔ)渔欢,本文不做介紹墓塌。@ohos.request模塊主要給應(yīng)用提供上傳下載文件、后臺(tái)傳輸代理的基礎(chǔ)能力。它具備任務(wù)管理系統(tǒng)的默認(rèn)并發(fā)功能苫幢,簡(jiǎn)化下載功能的實(shí)現(xiàn)和管理访诱,提升數(shù)據(jù)傳輸?shù)陌踩贤ㄖ獧C(jī)制韩肝,新增任務(wù)狀態(tài)與進(jìn)度查詢功能盐数,具有靈活性、高效性伞梯、可擴(kuò)展性、可靠性帚屉、一致性和安全性的優(yōu)勢(shì)谜诫。

具體來(lái)說(shuō),@ohos.request模塊包括以下功能:

  1. 任務(wù)管理:任務(wù)管理操作包括創(chuàng)建任務(wù)攻旦、暫停任務(wù)喻旷、恢復(fù)任務(wù)、刪除任務(wù)牢屋、文件上傳且预、文件下載、系統(tǒng)通知等烙无。創(chuàng)建的任務(wù)分為前端任務(wù)和后臺(tái)任務(wù)锋谐。前端任務(wù)是立即的、模態(tài)界面的截酷、同步的涮拗,跟隨應(yīng)用的生命周期,通常數(shù)據(jù)量較小迂苛、耗時(shí)短三热,例如發(fā)布微信朋友圈、微博三幻,通常優(yōu)先級(jí)高且傾斜帶寬資源就漾。后臺(tái)任務(wù)為可等待的、任意界面的念搬、異步的抑堡,通常數(shù)據(jù)量較大、耗時(shí)長(zhǎng)锁蠕,例如緩存一部電影夷野、同步數(shù)百兆字節(jié)乃至若干吉字節(jié)的數(shù)據(jù),優(yōu)先級(jí)相較于前端任務(wù)低且與應(yīng)用生命周期無(wú)關(guān)荣倾。

  2. 任務(wù)查詢管理:系統(tǒng)查詢所有任務(wù)悯搔、過(guò)濾上傳任務(wù)、過(guò)濾下載任務(wù)、過(guò)濾時(shí)間段內(nèi)任務(wù)妒貌、過(guò)濾前端任務(wù)通危、過(guò)濾后臺(tái)任務(wù)、用戶查詢指定任務(wù)信息灌曙、用戶查詢指定隱藏任務(wù)信息菊碟、系統(tǒng)查詢指定任務(wù)信息、系統(tǒng)清理指定任務(wù)等在刺。

  3. 任務(wù)自動(dòng)恢復(fù):網(wǎng)絡(luò)條件不滿足時(shí)任務(wù)不啟動(dòng)或者暫停逆害,滿足后自動(dòng)啟動(dòng)或者恢復(fù)(需要HTTP服務(wù)器支持?jǐn)帱c(diǎn)續(xù)傳)。

  4. 安全隱私保護(hù):包括網(wǎng)絡(luò)權(quán)限檢查蚣驼、普通接口僅操作自己創(chuàng)建的任務(wù)魄幕、任務(wù)信息加密存儲(chǔ)、系統(tǒng)接口檢查颖杏、系統(tǒng)接口查詢隱匿任務(wù)敏感字段纯陨、普通接口查詢隱匿任務(wù)敏感字段、遍歷攻擊留储、DOS翼抠、僵尸任務(wù)、惡意的靜默后臺(tái)任務(wù)获讳、系統(tǒng)管理接口權(quán)限等阴颖。

  5. 日志:包括調(diào)試模式和發(fā)布模式。調(diào)試模式可打印所有內(nèi)存修改丐膝、磁盤膘盖、網(wǎng)絡(luò)讀寫、邏輯分支等日志尤误。發(fā)布模式下除了導(dǎo)致任務(wù)失敗侠畔、服務(wù)異常的日志,其余日志都會(huì)關(guān)閉损晤。

  6. 任務(wù)失敗重試:對(duì)于不可恢復(fù)的原因软棺,直接失敗尤勋;對(duì)于可恢復(fù)的原因喘落,網(wǎng)絡(luò)斷開(kāi)、網(wǎng)絡(luò)類型不匹配等最冰,不現(xiàn)場(chǎng)重試瘦棋,任務(wù)到等待網(wǎng)絡(luò)恢復(fù)隊(duì)列;網(wǎng)絡(luò)超時(shí)則就地重試1次暖哨,仍網(wǎng)絡(luò)超時(shí)赌朋,則立即失敗。

  7. 服務(wù)按需啟停:上傳下載服務(wù)不隨系統(tǒng)自啟。應(yīng)用主動(dòng)調(diào)用任意接口沛慢,上傳下載服務(wù)自動(dòng)啟動(dòng)赡若。網(wǎng)絡(luò)連接事件會(huì)觸發(fā)上傳下載服務(wù)啟動(dòng)。在任務(wù)隊(duì)列中团甲,沒(méi)有正在處理的任務(wù)逾冬,或者等待網(wǎng)絡(luò)恢復(fù)的任務(wù),延遲10秒鐘躺苦,再check一次身腻,仍舊沒(méi)有的,則通知系統(tǒng)服務(wù)框架(SAMGR)可以停止并卸載上傳下載服務(wù)匹厘。在服務(wù)退出過(guò)程中霸株,新的接口請(qǐng)求可能失敗,在客戶端檢查服務(wù)狀態(tài)集乔、通過(guò)重試按需啟動(dòng)。

  8. 通知:任務(wù)從第一次開(kāi)始到最終結(jié)束都應(yīng)該有進(jìn)度通知坡椒。目前采用固定時(shí)間間隔觸發(fā)進(jìn)度通知扰路,前臺(tái)任務(wù)1秒,后臺(tái)任務(wù)3秒倔叼。任務(wù)狀態(tài)的每次變化也要觸發(fā)進(jìn)度通知汗唱。當(dāng)任務(wù)完成和失敗,則觸發(fā)其專用的進(jìn)度通知丈攒。提供了抑制開(kāi)關(guān)哩罪,可以在創(chuàng)建任務(wù)時(shí)打開(kāi),以避免頻繁通知巡验。

下載任務(wù)的狀態(tài)遷移流程

使用@ohos.request模塊執(zhí)行下載的任務(wù)际插,具有四種運(yùn)行狀態(tài):初始任務(wù)、就緒任務(wù)显设、掛起任務(wù)框弛、待網(wǎng)任務(wù)、成功任務(wù)捕捂、失敗任務(wù)瑟枫。可以通過(guò)create創(chuàng)建任務(wù)指攒,start開(kāi)始任務(wù)慷妙,pause掛起任務(wù),resume恢復(fù)任務(wù)允悦,remove移除任務(wù)膝擂,stop停止任務(wù),任務(wù)結(jié)果有final-failed任務(wù)失敗,final-completed下載完成猿挚,recoverable-failed重試失敗咐旧,并支持查詢?nèi)蝿?wù)狀態(tài),具體流程如圖一所示:

圖一 模塊流程圖

常見(jiàn)場(chǎng)景與方案

場(chǎng)景1:低帶寬網(wǎng)絡(luò)上傳瑣碎文件場(chǎng)景

在網(wǎng)絡(luò)連接較差绩蜻,低帶寬的網(wǎng)絡(luò)環(huán)境中铣墨,HTTP連接的建立耗時(shí)可能會(huì)大幅提升。這時(shí)候進(jìn)行數(shù)據(jù)壓縮可以加快頁(yè)面加載速度办绝,并減少HTTP請(qǐng)求數(shù)量和移動(dòng)數(shù)據(jù)流量伊约。

場(chǎng)景2:處理大量資源的場(chǎng)景

如應(yīng)用商店、網(wǎng)盤應(yīng)用等孕蝉,這類應(yīng)用通常擁有大體積的文件資源屡律。當(dāng)用戶從暫停或者斷網(wǎng)中重新恢復(fù)時(shí)降淮,如果從頭開(kāi)始上傳下載則會(huì)額外耗費(fèi)大量的時(shí)間超埋。此時(shí)可以采用斷點(diǎn)續(xù)傳方法進(jìn)行上傳下載。

數(shù)據(jù)壓縮

數(shù)據(jù)壓縮是指在應(yīng)用中對(duì)數(shù)據(jù)進(jìn)行壓縮佳鳖,以減少存儲(chǔ)空間和數(shù)據(jù)傳輸量霍殴、節(jié)省帶寬,提高加載速度系吩。數(shù)據(jù)壓縮通常在網(wǎng)絡(luò)傳輸和存儲(chǔ)方面發(fā)揮著重要作用来庭,特別是在處理大量數(shù)據(jù)或需要頻繁傳輸數(shù)據(jù)的場(chǎng)景下。

在應(yīng)用開(kāi)發(fā)中穿挨,常見(jiàn)的數(shù)據(jù)壓縮技術(shù)分類如下:

  • 有損壓縮:僅限圖片視頻音頻等文件適用月弛。通過(guò)減少圖片視頻文件的分辨率,降低音頻的音質(zhì)等手段科盛,以減少文件的大小帽衙,來(lái)實(shí)現(xiàn)減少加載時(shí)間和帶寬消耗。
  • 無(wú)損壓縮:對(duì)一些零碎文件可以使用 @ohos.zlib(Zip模塊)來(lái)進(jìn)行打包壓縮贞绵,減少上傳請(qǐng)求次數(shù)佛寿;對(duì)一些大文件可以利用緩存技術(shù),服務(wù)器將曾經(jīng)上傳過(guò)的大文件MD5碼緩存起來(lái)但壮,本地在上傳前預(yù)生成MD5碼并傳輸?shù)椒?wù)器進(jìn)行比對(duì)冀泻,如果相同則說(shuō)明服務(wù)器存在該文件,可以跳過(guò)該文件上傳蜡饵,從而省略重復(fù)傳輸時(shí)間弹渔。

以從相冊(cè)批量上傳圖片為例,介紹大量文件打包無(wú)損壓縮上傳相關(guān)技術(shù)溯祸,下圖為相關(guān)示例的界面截圖:

圖二 相冊(cè)批量上傳圖片示例圖

以批量上傳照片(分辨率為480*640肢专,24位舞肆,平均大小50~120KB)為例,在RK設(shè)備上測(cè)試的結(jié)果如下表所示:

上傳照片數(shù)量 優(yōu)化前耗時(shí)(ms) 優(yōu)化后耗時(shí)(ms)
10 470 526
20 1124 1091
... ... ...
50 2379 2138
80 3950 3258
... ... ...
100 5276 3909

圖三 上傳數(shù)量和耗時(shí)對(duì)比圖表

由于上傳耗時(shí)收到網(wǎng)絡(luò)狀態(tài)影響偏差較大博杖,結(jié)果取的幾次測(cè)量結(jié)果的最小值椿胯。但是仍然可以從數(shù)據(jù)中看出,優(yōu)化前的耗時(shí)基本為線性增長(zhǎng)剃根,壓縮優(yōu)化后的耗時(shí)在上傳文件數(shù)量較低時(shí)并不明顯哩盲,還會(huì)因?yàn)槎嘤嗟膲嚎s處理影響耗時(shí)。不過(guò)隨著上傳的照片數(shù)量增多狈醉,優(yōu)化后的耗時(shí)和優(yōu)化之前的耗時(shí)差距越來(lái)越明顯廉油,優(yōu)化效果越好。

數(shù)據(jù)壓縮的相關(guān)示例代碼如下:

  1. 導(dǎo)入相關(guān)模塊:
import common from '@ohos.app.ability.common';
import fs from '@ohos.file.fs';
import zlib from '@ohos.zlib';
  1. 創(chuàng)建壓縮上傳相關(guān)類:
class ZipUpload {
  // 創(chuàng)建任務(wù)前存放的uri
  private waitList: Array<string> = [];
  // 需要上傳的文件uri
  private fileUris: Array<string> = [];
  ...
}
  1. 建立用于接收?qǐng)D庫(kù)圖片的臨時(shí)文件夾苗傅,并將整個(gè)臨時(shí)文件夾打包添加到待上傳list內(nèi):
// 文件壓縮處理
async zipUploadFiles(fileUris: Array<string>): Promise<void> {
  this.context = getContext(this) as common.UIAbilityContext;
  let cacheDir = this.context.cacheDir;
  let tempDir = fs.mkdtempSync(`${cacheDir}/XXXXXX`);
  // 將圖庫(kù)圖片獲取的uri放入fileUris中抒线,遍歷復(fù)制到臨時(shí)文件夾
  for (let i = 0; i < fileUris.length; i++) {
    let fileName = fileUris[i].split('/').pop();
    let resourceFile: fs.File = fs.openSync(fileUris[i], fs.OpenMode.READ_ONLY);
    fs.copyFileSync(resourceFile.fd, `${tempDir}/${fileName}`, 0);
    fs.closeSync(resourceFile);
  }
  // 文件壓縮,將之前生成的臨時(shí)文件夾內(nèi)打包到test.zip內(nèi)
  let options: zlib.Options = {
    level: zlib.CompressLevel.COMPRESS_LEVEL_DEFAULT_COMPRESSION,
    memLevel: zlib.MemLevel.MEM_LEVEL_DEFAULT,
    strategy: zlib.CompressStrategy.COMPRESS_STRATEGY_DEFAULT_STRATEGY
  };
  let data = await zlib.compressFile(tempDir, `${cacheDir}/test.zip`, options);
  // 刪除臨時(shí)文件夾
  fs.rmdirSync(tempDir);
  // 將生成的zip包放到傳輸隊(duì)列
  this.waitList.push(`${cacheDir}/test.zip`);
}

斷點(diǎn)續(xù)傳

斷點(diǎn)續(xù)傳功能的實(shí)現(xiàn)渣慕,不管是應(yīng)用端還是服務(wù)器端都需要用到合理的技術(shù)來(lái)互相協(xié)同嘶炭。在實(shí)際開(kāi)發(fā)中,開(kāi)發(fā)者無(wú)需親自實(shí)現(xiàn)斷點(diǎn)續(xù)傳功能逊桦,只需對(duì)SDK進(jìn)行合理配置眨猎。

在應(yīng)用端需要用到的技術(shù)和API:

  • @ohos.file.fs(文件管理):用于處理文件上傳操作,提供了讀取文件內(nèi)容卫袒,文件分片和組合的功能。
  • @ohos.file.hash(文件哈希處理):用于實(shí)現(xiàn)文件MD5的計(jì)算单匣,將計(jì)算的MD5值預(yù)先傳到服務(wù)器端進(jìn)行預(yù)處理夕凝,實(shí)現(xiàn)文件秒傳,同時(shí)確保傳輸?shù)臏?zhǔn)確性和可靠性户秤。
  • @ohos.request(上傳下載):用于實(shí)現(xiàn)文件上傳操作码秉,并支持在上傳過(guò)程中的斷點(diǎn)續(xù)傳功能。

在服務(wù)器端需要用到的技術(shù):

  • 協(xié)議需要支持Range:用于在服務(wù)器端支持范圍請(qǐng)求鸡号,方便處理文件上傳下載斷點(diǎn)續(xù)傳功能转砖。
  • 文件校驗(yàn)相關(guān)邏輯:需要實(shí)現(xiàn)校驗(yàn)文件是否有錯(cuò),確保在傳輸中斷后能夠準(zhǔn)確恢復(fù)并繼續(xù)傳輸鲸伴。

通過(guò)結(jié)合應(yīng)用端和服務(wù)器端的相關(guān)技術(shù)府蔗,可以共同實(shí)現(xiàn)高效且可靠的文件斷點(diǎn)續(xù)傳功能,提供更好的用戶體驗(yàn)并確保數(shù)據(jù)傳輸?shù)姆€(wěn)定性汞窗。

文件上傳

對(duì)于大文件斷點(diǎn)續(xù)傳上傳姓赤,本文采用@ohos.request(上傳下載)模塊中的request.agent任務(wù)托管接口,可以自動(dòng)實(shí)現(xiàn)暫停繼續(xù)重試等操作仲吏,無(wú)需手動(dòng)將文件分片和記錄上傳分片信息不铆。流程圖如圖四所示:

圖四 斷點(diǎn)續(xù)傳上傳流程圖

斷點(diǎn)續(xù)傳上傳示例代碼如下:

  1. 導(dǎo)入相關(guān)模塊:
import common from '@ohos.app.ability.common';
import request from '@ohos.request';
  1. 創(chuàng)建相關(guān)上傳類:
class Upload {
  // 后臺(tái)任務(wù)
  private backgroundTask: request.agent.Task | undefined = undefined;
  // 創(chuàng)建任務(wù)前存放的uri
  private waitList: Array<string> = [];
  ...
}
  1. 生成MD5碼蝌焚,上傳到服務(wù)器進(jìn)行校驗(yàn):
async checkFileExist(fileUri: string): Promise<boolean> {
  let httpRequest = http.createHttp();
  // 生成md5碼
  let md5 = await hash.hash(fileUri, 'md5');
  let requestOption: http.HttpRequestOptions = {
    method: http.RequestMethod.POST,
    extraData: {
      'MD5': md5
    }
  }
  let response = await httpRequest.request('http://XXX.XXX.XXX.XXX/XXXX', requestOption);
  let result = response.result;
  let flag = false;
  ... // 根據(jù)服務(wù)器返回對(duì)應(yīng)數(shù)據(jù)判斷是否存在
  if (flag) {
    return true;
  } else {
    return false;
  }
}
  1. 配置Config,創(chuàng)建后臺(tái)上傳任務(wù):
private config: request.agent.Config = {
  action: request.agent.Action.UPLOAD,
  headers: HEADER,
  url: '',
  mode: request.agent.Mode.BACKGROUND,
  method: 'POST',
  title: 'upload',
  network: request.agent.Network.ANY,
  data: [],
  token: 'UPLOAD_TOKEN'
}
...
// 轉(zhuǎn)換uri
private async getFilesAndData(cacheDir: string, fileUris: Array<string>): Promise<Array<request.agent.FormItem>> {
...
}
// 創(chuàng)建文件上傳后臺(tái)任務(wù)
async createBackgroundTask(fileUris: Array<string>) {
 // 獲取上傳url
  this.config.url = 'http://XXX.XXX.XXX.XXX';
  this.config.mode = request.agent.Mode.BACKGROUND;
  let tempData = await this.getFilesAndData(this.context.cacheDir, fileUris);
  // 判斷每個(gè)文件是否為空
  for (let i = 0; i < tempData.length; i++) {
    let flag = await this.checkFileExist(`${this.context.cacheDir}/${tempData[i].name}`);
    if (!flag) {
      this.config.data.push(tempData[i])
    }
  }
  let isFileExist = await this.checkFileExist(`${this.context.cacheDir}/${this.config.data[0].name}`);
  if (this.config.data.length === 0) {
    return;
  }
  this.backgroundTask = await request.agent.create(this.context, this.config);
}
  1. 任務(wù)開(kāi)始:
await this.backgroundTask.start();
  1. 任務(wù)暫停:
async pause() {
  if (this.backgroundTask === undefined) {
    return;
  }
  await this.backgroundTask.pause();
}
  1. 任務(wù)繼續(xù):
async resume() {
  if (this.backgroundTask === undefined) {
    return;
  }
  await this.backgroundTask.resume();
}

文件下載

對(duì)于大文件斷點(diǎn)續(xù)傳下載誓斥,也可以直接調(diào)用request.agent接口只洒,該接口的斷點(diǎn)續(xù)傳是基于HTTP協(xié)議Header里的Range字段實(shí)現(xiàn)的,在任務(wù)暫停重啟的時(shí)候劳坑,會(huì)自動(dòng)設(shè)置Header中的Range字段毕谴,無(wú)需進(jìn)行額外的配置。

Range簡(jiǎn)介

HTTP協(xié)議里面的Range字段泡垃,官方名稱為范圍請(qǐng)求析珊,它允許服務(wù)器只發(fā)送 HTTP
消息的一部分到客戶端,可以用來(lái)請(qǐng)求部分?jǐn)?shù)據(jù)而不是整個(gè)資源蔑穴。

Range的格式通常是Range:
<unit>=<start>-<end>忠寻,其中<unit>表示范圍所采用的單位,通常是字節(jié)(bytes)存和,<start><end> 表示請(qǐng)求的起始字節(jié)和結(jié)束字節(jié)的位置奕剃。

Range語(yǔ)法如下:

// 表示從range-start到文件末尾
Range: <unit>=<range-start>-
// 表示從range-start到range-end
Range: <unit>=<range-start>-<range-end>
// 可以同時(shí)選擇多段,用逗號(hào)分隔
Range: <unit>=<range-start>-<range-end>, <range-start>-<range-end>

// 示例:表示返回1024 bytes之后的文件
Range: bytes=1024-

服務(wù)器收到請(qǐng)求后捐腿,正確處理請(qǐng)求會(huì)回復(fù)206 Partial
Content纵朋,未正常處理則會(huì)回復(fù)其他響應(yīng)碼。下表是服務(wù)器回復(fù)的常見(jiàn)響應(yīng)碼:

服務(wù)器響應(yīng)碼 常見(jiàn)的原因
206 Partial Content 服務(wù)器收到正常Range請(qǐng)求的響應(yīng)碼茄袖,返回部分內(nèi)容的響應(yīng)操软。
416 Range Not Satisfiable 所請(qǐng)求的范圍不合法,表示服務(wù)器錯(cuò)誤宪祥。
200 OK 服務(wù)器忽略了 Range 首部聂薪,返回整個(gè)文件。

斷點(diǎn)續(xù)傳下載示例代碼如下:

  1. 導(dǎo)入模塊:
import common from '@ohos.app.ability.common';
import request from '@ohos.request';
  1. 創(chuàng)建下載類:
class Download {
  // 任務(wù)存放前的uri
  private waitList: Array<string[]> = [];
  // 下載任務(wù)
  private downloadTask: request.agent.Task | undefined = undefined;
  // 后臺(tái)任務(wù)下載列表
  private backgroundDownloadTaskList: Array<request.agent.Task> = [];
  ...
}
  1. 配置Config蝗羊,創(chuàng)建后臺(tái)下載任務(wù):
async createBackgroundTask(downloadList: Array<string[]>) {
  let splitUrl = url.split('//')[1].split('/');
  let context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;
  let downloadConfig: request.agent.Config = {
    action: request.agent.Action.DOWNLOAD,
    url: url,
    method: 'POST',
    title: 'download',
    mode: request.agent.Mode.FOREGROUND, // 必須是后臺(tái)任務(wù)才能續(xù)傳
    network: request.agent.Network.ANY,
    saveas: `./${folder}/${splitUrl[splitUrl.length-1]}`,
    overwrite: true
  }
  this.downloadTask = await request.agent.create(context, downloadConfig);
  if (this.backgroundDownloadTaskList.findIndex(task => task.config.url === downTask.config.url) === -1) {
    this.backgroundDownloadTaskList.push(downTask);
  }
}
  1. 任務(wù)開(kāi)始:
...
await downTask.start();
...
  1. 任務(wù)暫停:
async pause() {
  if (this.backgroundDownloadTaskList.length === 0) {
    return;
  }
  this.backgroundDownloadTaskList.forEach(async task => {
    await task.pause();
  })
}
  1. 任務(wù)繼續(xù):
async resume() {
  if (this.backgroundDownloadTaskList.length === 0) {
    return;
  }
  this.backgroundDownloadTaskList.forEach(async task => {
    await task.resume();
  })
}
  1. 任務(wù)停止:
async deleteAllBackTasks() {
  if (this.backgroundDownloadTaskList.length > 0) {
    this.backgroundDownloadTaskList.forEach(async task => {
      await request.agent.remove(task.tid);
    })
    this.backgroundDownloadTaskList = [];
  }
}

寫在最后

如果你覺(jué)得這篇內(nèi)容對(duì)你還蠻有幫助藏澳,我想邀請(qǐng)你幫我三個(gè)小忙

  • 點(diǎn)贊,轉(zhuǎn)發(fā)耀找,有你們的 『點(diǎn)贊和評(píng)論』翔悠,才是我創(chuàng)造的動(dòng)力。
  • 關(guān)注小編野芒,同時(shí)可以期待后續(xù)文章ing??蓄愁,不定期分享原創(chuàng)知識(shí)。
  • 想要獲取更多完整鴻蒙最新學(xué)習(xí)知識(shí)點(diǎn)狞悲,請(qǐng)移步前往小編:https://gitee.com/MNxiaona/733GH/blob/master/jianshu
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末涝登,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子效诅,更是在濱河造成了極大的恐慌胀滚,老刑警劉巖趟济,帶你破解...
    沈念sama閱讀 217,542評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異咽笼,居然都是意外死亡顷编,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門剑刑,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)媳纬,“玉大人,你說(shuō)我怎么就攤上這事施掏∨セ荩” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 163,912評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵七芭,是天一觀的道長(zhǎng)素挽。 經(jīng)常有香客問(wèn)我,道長(zhǎng)狸驳,這世上最難降的妖魔是什么预明? 我笑而不...
    開(kāi)封第一講書人閱讀 58,449評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮耙箍,結(jié)果婚禮上撰糠,老公的妹妹穿的比我還像新娘。我一直安慰自己辩昆,他們只是感情好阅酪,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著汁针,像睡著了一般术辐。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上扇丛,一...
    開(kāi)封第一講書人閱讀 51,370評(píng)論 1 302
  • 那天术吗,我揣著相機(jī)與錄音尉辑,去河邊找鬼帆精。 笑死,一個(gè)胖子當(dāng)著我的面吹牛隧魄,可吹牛的內(nèi)容都是我干的卓练。 我是一名探鬼主播,決...
    沈念sama閱讀 40,193評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼购啄,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼襟企!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起狮含,我...
    開(kāi)封第一講書人閱讀 39,074評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤顽悼,失蹤者是張志新(化名)和其女友劉穎曼振,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體蔚龙,經(jīng)...
    沈念sama閱讀 45,505評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡冰评,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評(píng)論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了木羹。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片甲雅。...
    茶點(diǎn)故事閱讀 39,841評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖坑填,靈堂內(nèi)的尸體忽然破棺而出抛人,到底是詐尸還是另有隱情,我是刑警寧澤脐瑰,帶...
    沈念sama閱讀 35,569評(píng)論 5 345
  • 正文 年R本政府宣布妖枚,位于F島的核電站,受9級(jí)特大地震影響蚪黑,放射性物質(zhì)發(fā)生泄漏盅惜。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評(píng)論 3 328
  • 文/蒙蒙 一忌穿、第九天 我趴在偏房一處隱蔽的房頂上張望抒寂。 院中可真熱鬧,春花似錦掠剑、人聲如沸屈芜。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,783評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)井佑。三九已至,卻和暖如春眠寿,著一層夾襖步出監(jiān)牢的瞬間躬翁,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,918評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工盯拱, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留盒发,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,962評(píng)論 2 370
  • 正文 我出身青樓狡逢,卻偏偏與公主長(zhǎng)得像宁舰,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子奢浑,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容