j.s異步編程4

async function fileSizes(files) {
  let lines = files.map(async fileName => {
    return fileName + ": " +
      (await textFile(fileName)).length;
  });
  return (await Promise.all(lines)).join("\n");
}

修正后的異步文件大小收集函數(shù)解析

這個(gè)改進(jìn)版的 fileSizes 函數(shù)解決了之前的競(jìng)爭(zhēng)條件問(wèn)題,讓我們分析它的工作原理:

代碼功能與改進(jìn)

async function fileSizes(files) {
  // 1. 創(chuàng)建Promise數(shù)組(不立即執(zhí)行拼接)
  let lines = files.map(async fileName => {
    return fileName + ": " +
      (await textFile(fileName)).length; // 返回單個(gè)文件的結(jié)果
  });
  
  // 2. 等待所有Promise完成并收集結(jié)果
  return (await Promise.all(lines)).join("\n");
  // 等價(jià)于:
  // const results = await Promise.all(lines);
  // return results.join("\n");
}

核心改進(jìn)

  1. 避免共享狀態(tài)修改:不再直接操作共享的 list 變量
  2. 結(jié)果隔離:每個(gè)異步操作返回獨(dú)立的字符串結(jié)果
  3. 統(tǒng)一合并:使用 Promise.all 等待所有結(jié)果完成后,再一次性拼接

執(zhí)行流程詳解

假設(shè)有三個(gè)文件:

const files = ["a.txt", "b.txt", "c.txt"];
  1. 生成Promise數(shù)組

    files.map(...)
    
    • 為每個(gè)文件創(chuàng)建一個(gè)異步任務(wù)
    • 每個(gè)任務(wù)返回一個(gè) Promise,解析為對(duì)應(yīng)文件的結(jié)果字符串
  2. 并行執(zhí)行異步任務(wù)

    await Promise.all(lines)
    
    • 并行讀取所有文件
    • 等待所有文件讀取完成
    • 結(jié)果數(shù)組順序與原始 files 數(shù)組一致
  3. 拼接最終結(jié)果

    (await Promise.all(lines)).join("\n")
    
    • 將結(jié)果數(shù)組按原始順序拼接成字符串
    • 保證輸出順序與輸入文件順序一致

關(guān)鍵技術(shù)點(diǎn)

  1. Promise.all 的順序保證

    • 即使異步任務(wù)完成時(shí)間不同
    • Promise.all 返回的結(jié)果數(shù)組順序始終與輸入 Promise 數(shù)組一致
  2. 避免競(jìng)態(tài)條件

    // 之前的錯(cuò)誤寫法(共享狀態(tài)修改)
    list += ... // 非原子操作,多任務(wù)沖突
    
    // 現(xiàn)在的正確寫法(獨(dú)立結(jié)果)
    return ... // 每個(gè)任務(wù)返回獨(dú)立值,無(wú)共享狀態(tài)
    
  3. 異步映射與聚合

    files.map(async ...) // 映射為Promise數(shù)組
    Promise.all(...)     // 聚合所有結(jié)果
    results.join("\n")   // 按序拼接
    

烏鴉的異步智慧應(yīng)用

在卡拉的LED項(xiàng)目中,類似的模式可以用于并行控制多個(gè)屏幕:

async function updateAllScreens(frames) {
  // 1. 為每個(gè)屏幕創(chuàng)建更新任務(wù)
  const updateTasks = screenAddresses.map((addr, index) => {
    return sendCommand(addr, "update", frames[index])
      .then(() => `${addr} 更新成功`)
      .catch(err => `${addr} 更新失敗: ${err.message}`);
  });
  
  // 2. 等待所有任務(wù)完成并收集結(jié)果
  const results = await Promise.all(updateTasks);
  
  // 3. 生成匯總報(bào)告(順序與屏幕數(shù)組一致)
  return results.join("\n");
}

這種設(shè)計(jì)確保了:

  1. 所有屏幕更新請(qǐng)求并行發(fā)送
  2. 無(wú)論響應(yīng)順序如何,結(jié)果都按屏幕原始順序排列
  3. 避免了多個(gè)屏幕更新操作之間的數(shù)據(jù)競(jìng)爭(zhēng)

就像烏鴉同時(shí)處理多個(gè)堅(jiān)果一樣,每個(gè)堅(jiān)果都獨(dú)立處理,最后按順序整齊排列。 ???

這類錯(cuò)誤很容易犯,尤其是在使用 await 時(shí),你應(yīng)當(dāng)留意代碼中存在執(zhí)行間隙的位置。JavaScript 顯式的異步機(jī)制(無(wú)論是通過(guò)回調(diào)、Promise 還是 await)有一個(gè)優(yōu)勢(shì):相對(duì)容易發(fā)現(xiàn)這些間隙的位置。

總結(jié)

異步編程使程序能夠在等待長(zhǎng)時(shí)間操作時(shí)不凍結(jié)整個(gè)系統(tǒng)成為可能。JavaScript 環(huán)境通常使用回調(diào)函數(shù)(即操作完成時(shí)被調(diào)用的函數(shù))來(lái)實(shí)現(xiàn)這種編程風(fēng)格。事件循環(huán)會(huì)在適當(dāng)?shù)臅r(shí)候調(diào)度這些回調(diào)函數(shù)依次執(zhí)行,因此它們的執(zhí)行不會(huì)重疊。

Promise(表示未來(lái)可能完成的操作的對(duì)象)和 async 函數(shù)(允許你像編寫同步程序一樣編寫異步程序)使異步編程變得更加容易。

異步編程的陷阱與核心要點(diǎn)解析

這類錯(cuò)誤很容易犯,尤其是在使用 await 時(shí),你需要清楚代碼中哪些地方存在執(zhí)行間隙。JavaScript 顯式的異步機(jī)制(無(wú)論是通過(guò)回調(diào)、Promise 還是 await)有一個(gè)優(yōu)點(diǎn):相對(duì)容易發(fā)現(xiàn)這些間隙的位置。

核心總結(jié)

1. 異步編程的本質(zhì)

異步編程使得程序在等待耗時(shí)操作時(shí)不會(huì)凍結(jié)整個(gè)系統(tǒng)。JavaScript 環(huán)境通常通過(guò)回調(diào)函數(shù)實(shí)現(xiàn)這種編程模式——回調(diào)函數(shù)會(huì)在操作完成時(shí)被調(diào)用。事件循環(huán)(Event Loop)負(fù)責(zé)調(diào)度這些回調(diào),確保它們按順序執(zhí)行,不會(huì)重疊。

2. 異步機(jī)制的演進(jìn)

  • 回調(diào)函數(shù)(Callbacks):傳統(tǒng)異步處理方式,但容易導(dǎo)致“回調(diào)地獄”(Callback Hell)。
  • Promise:用對(duì)象封裝未來(lái)可能完成的操作,通過(guò) .then().catch() 處理結(jié)果,避免回調(diào)嵌套。
  • async/await:以同步代碼的寫法實(shí)現(xiàn)異步邏輯,使異步流程更直觀,可讀性更高。

3. 關(guān)鍵優(yōu)勢(shì)與注意事項(xiàng)

  • 非阻塞特性:異步操作在等待時(shí)釋放主線程,允許程序處理其他事件(如用戶輸入、UI 渲染)。
  • 顯式間隙管理:通過(guò) Promise 和 await,可以清晰識(shí)別代碼中的異步間隙,避免共享狀態(tài)導(dǎo)致的競(jìng)態(tài)條件(Race Conditions)。
  • 錯(cuò)誤處理:Promise 的 .catch()try/catch 結(jié)合 await,能更優(yōu)雅地捕獲異步操作中的異常。

烏鴉的異步哲學(xué)

在卡拉的LED燈光系統(tǒng)中,異步編程是實(shí)現(xiàn)復(fù)雜動(dòng)畫的核心。例如,當(dāng)她需要讓九個(gè)屏幕依次顯示不同的像素圖案時(shí):

async function animateCrowFlight() {
  for (const frame of flightFrames) {
    // 并行更新所有屏幕(非阻塞)
    await Promise.all(screenAddresses.map(addr => 
      displayFrameOnScreen(addr, frame[addr])
    ));
    
    // 等待動(dòng)畫間隔,期間可響應(yīng)其他事件(如緊急停止信號(hào))
    await wait(100); 
  }
}

這里的 await 并非阻塞主線程,而是讓事件循環(huán)在等待時(shí)處理其他任務(wù)(如傳感器輸入)。這種機(jī)制讓卡拉的程序既能實(shí)現(xiàn)精密的動(dòng)畫同步,又能保持對(duì)外部事件的實(shí)時(shí)響應(yīng)——就像烏鴉在飛行中同時(shí)觀察周圍環(huán)境,隨時(shí)調(diào)整方向。

異步編程的智慧,本質(zhì)上是對(duì)“時(shí)間間隙”的掌控。正如JavaScript用事件循環(huán)調(diào)度回調(diào),烏鴉用代碼間隙處理突發(fā)情況,兩者都在無(wú)序中創(chuàng)造出有序的節(jié)奏。 ?????

練習(xí)題:活動(dòng)時(shí)間分析

卡拉實(shí)驗(yàn)室附近有一個(gè)由運(yùn)動(dòng)傳感器激活的安全攝像頭。它連接到網(wǎng)絡(luò),激活時(shí)會(huì)發(fā)送視頻流。為避免被發(fā)現(xiàn),卡拉設(shè)置了一個(gè)系統(tǒng),該系統(tǒng)會(huì)檢測(cè)這種無(wú)線網(wǎng)絡(luò)流量,并在室外有活動(dòng)時(shí)在她的巢穴中點(diǎn)亮一盞燈,以便她知道何時(shí)需要保持安靜。

她還記錄了攝像頭被觸發(fā)的時(shí)間,并希望利用這些信息來(lái)可視化顯示平均一周中哪些時(shí)間段通常安靜,哪些時(shí)間段通常繁忙。日志存儲(chǔ)在文件中,每行包含一個(gè)時(shí)間戳數(shù)字(由 Date.now() 返回)。

1695709940692
1695701068331
1695701189163

camera_logs.txt 文件包含一個(gè)日志文件列表。編寫一個(gè)異步函數(shù) activityTable(day),它接收一周中的某一天作為參數(shù),并返回一個(gè)包含24個(gè)數(shù)字的數(shù)組,數(shù)組中的每個(gè)數(shù)字表示該天對(duì)應(yīng)小時(shí)內(nèi)觀察到的攝像頭網(wǎng)絡(luò)流量次數(shù)。天數(shù)使用 Date.getDay 方法的編號(hào)系統(tǒng)(星期日為0,星期六為6)。

沙箱環(huán)境提供的 activityGraph 函數(shù)可以將這樣的數(shù)組匯總為一個(gè)字符串。

要讀取文件,請(qǐng)使用前面定義的 textFile 函數(shù)——給定一個(gè)文件名,它返回一個(gè)解析為文件內(nèi)容的 Promise。請(qǐng)記住,new Date(timestamp) 會(huì)創(chuàng)建該時(shí)間的 Date 對(duì)象,該對(duì)象具有返回星期幾和小時(shí)的 getDaygetHours 方法。

兩種類型的文件——日志文件列表和日志文件本身——都將每條數(shù)據(jù)單獨(dú)放在一行,用換行符(\n)分隔。

async function activityTable(day) {
  let logFileList = await textFile("camera_logs.txt");
  // Your code here
}

activityTable(1)
  .then(table => console.log(activityGraph(table)));

異步活動(dòng)時(shí)間表函數(shù)解析

這個(gè) activityTable 函數(shù)的任務(wù)是統(tǒng)計(jì)特定星期幾(如星期一)每小時(shí)的攝像頭活動(dòng)次數(shù)。讓我們逐步解析如何實(shí)現(xiàn)它:

代碼框架與核心邏輯

async function activityTable(day) {
  // 1. 讀取日志文件列表
  let logFileList = await textFile("camera_logs.txt");
  
  // 2. 初始化24小時(shí)計(jì)數(shù)器數(shù)組
  const hourlyCounts = Array(24).fill(0);
  
  // 3. 解析日志文件列表并并行處理每個(gè)日志文件
  const logFiles = logFileList.trim().split('\n');
  await Promise.all(logFiles.map(async logFileName => {
    // 4. 讀取單個(gè)日志文件內(nèi)容
    const logContent = await textFile(logFileName);
    
    // 5. 解析每行時(shí)間戳并過(guò)濾指定星期幾的記錄
    logContent.trim().split('\n').forEach(timestamp => {
      const date = new Date(Number(timestamp));
      if (date.getDay() === day) {
        const hour = date.getHours();
        hourlyCounts[hour]++; // 增加對(duì)應(yīng)小時(shí)的計(jì)數(shù)
      }
    });
  }));
  
  // 6. 返回統(tǒng)計(jì)結(jié)果
  return hourlyCounts;
}

關(guān)鍵步驟詳解

  1. 讀取日志文件列表

    let logFileList = await textFile("camera_logs.txt");
    
    • 調(diào)用 textFile 異步獲取日志文件列表內(nèi)容
    • 返回類似:"log1.txt\nlog2.txt\nlog3.txt"
  2. 初始化計(jì)數(shù)器數(shù)組

    const hourlyCounts = Array(24).fill(0);
    
    • 創(chuàng)建長(zhǎng)度為24的數(shù)組,初始值全為0
    • 索引0-23對(duì)應(yīng)00:00-23:00小時(shí)
  3. 解析并并行處理日志文件

    const logFiles = logFileList.trim().split('\n');
    await Promise.all(logFiles.map(...));
    
    • 將文件列表按行分割為數(shù)組
    • 使用 Promise.all 并行處理所有日志文件
  4. 處理單個(gè)日志文件

    const logContent = await textFile(logFileName);
    logContent.trim().split('\n').forEach(timestamp => { ... });
    
    • 讀取日志文件內(nèi)容(多行時(shí)間戳)
    • 逐行解析每個(gè)時(shí)間戳
  5. 過(guò)濾并統(tǒng)計(jì)特定星期的活動(dòng)

    const date = new Date(Number(timestamp));
    if (date.getDay() === day) {
      const hour = date.getHours();
      hourlyCounts[hour]++;
    }
    
    • 將時(shí)間戳轉(zhuǎn)換為 Date 對(duì)象
    • 檢查是否為目標(biāo)星期(getDay() === day
    • 提取小時(shí)信息并更新對(duì)應(yīng)計(jì)數(shù)器

執(zhí)行流程示例

假設(shè) camera_logs.txt 包含:

monday.log
tuesday.log

執(zhí)行流程

  1. 讀取 camera_logs.txt 得到兩個(gè)日志文件名
  2. 并行讀取 monday.logtuesday.log
  3. 解析每個(gè)日志文件中的時(shí)間戳:
    1695709940692 → 2023-09-26 13:32:20 (星期二, 13點(diǎn))
    1695701068331 → 2023-09-26 11:24:28 (星期二, 11點(diǎn))
    1695701189163 → 2023-09-25 11:26:29 (星期一, 11點(diǎn))
    
  4. 若查詢 day=1(星期一):
    • 僅統(tǒng)計(jì) 1695701189163 這條記錄
    • hourlyCounts[11] = 1,其他小時(shí)為0

優(yōu)化與注意事項(xiàng)

  1. 錯(cuò)誤處理

    • 應(yīng)添加對(duì) textFile 可能失敗的處理
    • 示例:
      try {
        const logContent = await textFile(logFileName);
      } catch (err) {
        console.error(`讀取日志文件 ${logFileName} 失敗:`, err);
      }
      
  2. 內(nèi)存優(yōu)化

    • 對(duì)于極大的日志文件,可考慮流式處理而非一次性加載
  3. 性能考量

    • 并行處理所有日志文件可能導(dǎo)致資源耗盡
    • 可限制并發(fā)數(shù):
      await Promise.all(chunkArray(logFiles, 5).map(async chunk => {
        await Promise.all(chunk.map(handleFile));
      }));
      

烏鴉的數(shù)據(jù)分析智慧

在卡拉的安全系統(tǒng)中,這種時(shí)間分析可以幫助她:

  1. 識(shí)別最安全的活動(dòng)時(shí)段(如凌晨2-4點(diǎn))
  2. 預(yù)測(cè)人類巡邏的高峰期
  3. 優(yōu)化自己的作息以避開監(jiān)控密集時(shí)段

例如,通過(guò)分析 activityTable(1)(星期一)的結(jié)果,她可能發(fā)現(xiàn):

  • 11:00-13:00 活動(dòng)頻繁 → 對(duì)應(yīng)人類午餐時(shí)間
  • 03:00-05:00 幾乎無(wú)活動(dòng) → 理想的實(shí)驗(yàn)室工作時(shí)段

這種數(shù)據(jù)分析能力讓她在人類世界的夾縫中建立起自己的數(shù)字王國(guó),就像烏鴉利用城市垃圾桶的規(guī)律來(lái)規(guī)劃覓食路線一樣精準(zhǔn)。 ?????

練習(xí)題:原生 Promise 實(shí)現(xiàn)

題目要求
不使用 async/await 語(yǔ)法,而是使用原生的 Promise 方法(如 .then()、.catch()、Promise.all())重寫之前的 activityTable 函數(shù)。

參考答案

function activityTable(day) {
  return textFile("camera_logs.txt")
    .then(logFileList => {
      const logFiles = logFileList.trim().split('\n');
      const hourlyCounts = Array(24).fill(0);
      
      return Promise.all(logFiles.map(logFileName => {
        return textFile(logFileName)
          .then(logContent => {
            logContent.trim().split('\n').forEach(timestamp => {
              const date = new Date(Number(timestamp));
              if (date.getDay() === day) {
                hourlyCounts[date.getHours()]++;
              }
            });
          })
          .catch(err => {
            console.error(`Error reading log file ${logFileName}:`, err);
          });
      }))
      .then(() => hourlyCounts);
    })
    .catch(err => {
      console.error("Error reading camera_logs.txt:", err);
      throw err; // 可選:向上傳播錯(cuò)誤
    });
}

關(guān)鍵點(diǎn)解析

  1. Promise 鏈?zhǔn)秸{(diào)用

    • 不再使用 await,而是通過(guò) .then() 方法連接異步操作
    • 每個(gè) .then() 接收前一個(gè) Promise 的結(jié)果
  2. 并行處理

    • 使用 Promise.all() 并行讀取所有日志文件
    • 每個(gè)日志文件的處理結(jié)果(hourlyCounts 的更新)會(huì)被合并
  3. 錯(cuò)誤處理

    • 使用 .catch() 捕獲讀取文件時(shí)可能的錯(cuò)誤
    • 可選:通過(guò) throw err 將錯(cuò)誤繼續(xù)向上傳播
  4. 狀態(tài)管理

    • hourlyCounts 數(shù)組在閉包中被共享和修改
    • 所有日志文件處理完成后,最終返回該數(shù)組

與 async/await 的對(duì)比

特性 原生 Promise 實(shí)現(xiàn) async/await 實(shí)現(xiàn)
代碼結(jié)構(gòu) 鏈?zhǔn)秸{(diào)用(扁平化但嵌套仍存在) 同步風(fēng)格(更線性)
錯(cuò)誤處理 需要多個(gè) .catch() 或最終統(tǒng)一處理 單一的 try/catch
調(diào)試難度 調(diào)用??赡芨鼜?fù)雜 更接近同步代碼的調(diào)試體驗(yàn)
狀態(tài)共享 通過(guò)閉包隱式共享 顯式變量聲明
異步間隙可見性 更明顯(通過(guò) .then() 分隔) 隱藏在 await 之后

烏鴉的編程哲學(xué)

卡拉可能會(huì)選擇原生 Promise 實(shí)現(xiàn),因?yàn)樗N近底層機(jī)制,讓她能更精確地控制異步流程。在她的 LED 控制系統(tǒng)中,這種細(xì)粒度控制可能意味著:

  1. 并行與順序的精確平衡

    // 先獲取配置文件,再并行控制屏幕
    getConfig()
      .then(config => Promise.all(
        screens.map(screen => sendCommand(screen, config))
      ))
      .then(results => updateStatus(results));
    
  2. 優(yōu)雅降級(jí)策略

    fetchData()
      .catch(() => useFallbackData())
      .then(data => process(data));
    
  3. 資源限流

    // 控制并發(fā)數(shù),避免網(wǎng)絡(luò)過(guò)載
    function processWithLimit(items, limit) {
      let index = 0;
      const next = () => index < items.length 
        ? process(items[index++]).then(next) 
        : Promise.resolve();
      return Promise.all(Array(limit).fill().map(next));
    }
    

就像烏鴉用不同的喙部動(dòng)作處理不同類型的堅(jiān)果一樣,掌握多種異步編程范式能讓開發(fā)者在不同場(chǎng)景下選擇最合適的工具。 ?????

實(shí)現(xiàn)Promise_all函數(shù)

如我們所見,給定一個(gè)Promise數(shù)組,Promise.all會(huì)返回一個(gè)新的Promise,它等待數(shù)組中的所有Promise完成。當(dāng)所有Promise都成功時(shí),新Promise以包含所有結(jié)果的數(shù)組成功解析;如果其中任何一個(gè)Promise失敗,新Promise立即失敗,并傳遞第一個(gè)失敗Promise的原因。

現(xiàn)在需要你自己實(shí)現(xiàn)一個(gè)類似的函數(shù),命名為Promise_all。

注意:Promise一旦成功或失敗,就不能再次改變狀態(tài),后續(xù)對(duì)其resolve/reject函數(shù)的調(diào)用會(huì)被忽略。這一特性可以簡(jiǎn)化我們對(duì)Promise失敗的處理邏輯。

實(shí)現(xiàn)思路

核心邏輯

  1. 初始化狀態(tài)

    • 記錄已成功解析的Promise數(shù)量
    • 存儲(chǔ)所有Promise的解析結(jié)果(按原始順序)
    • 捕獲第一個(gè)失敗的Promise的原因
  2. 遍歷處理每個(gè)Promise

    • 為每個(gè)Promise綁定成功和失敗回調(diào)
    • 成功時(shí):將結(jié)果存入對(duì)應(yīng)位置,若所有Promise已成功,解析最終結(jié)果
    • 失敗時(shí):若尚未有失敗記錄,立即拒絕最終Promise
  3. 處理非Promise值

    • 若數(shù)組元素不是Promise,先將其轉(zhuǎn)換為已解析的Promise

參考實(shí)現(xiàn)

function Promise_all(promises) {
  return new Promise((resolve, reject) => {
    const results = new Array(promises.length); // 按順序存儲(chǔ)結(jié)果
    let completed = 0; // 已成功解析的Promise數(shù)量

    // 處理數(shù)組中的每個(gè)元素(可能是非Promise)
    promises.forEach((promise, index) => {
      // 將非Promise值轉(zhuǎn)換為已解析的Promise
      Promise.resolve(promise)
        .then(value => {
          results[index] = value; // 按索引存儲(chǔ)結(jié)果
          completed++; // 成功計(jì)數(shù)+1

          // 所有Promise都成功時(shí),解析最終結(jié)果
          if (completed === promises.length) {
            resolve(results);
          }
        })
        .catch(error => {
          // 第一個(gè)失敗的Promise決定最終結(jié)果
          if (!rejectCalled) { // 確保只處理一次失敗
            reject(error);
            rejectCalled = true; // 標(biāo)記已失敗
          }
        });
    });

    // 處理空數(shù)組的情況(所有Promise已完成)
    if (promises.length === 0) {
      resolve([]);
    }
  });
}

關(guān)鍵點(diǎn)解析

  1. 非Promise元素處理

    Promise.resolve(promise)
    
    • 確保數(shù)組中的每個(gè)元素都是Promise,統(tǒng)一用.then()處理
  2. 順序性保證

    • 使用索引index將結(jié)果存入對(duì)應(yīng)的位置
    • 最終結(jié)果數(shù)組的順序與輸入數(shù)組一致
  3. 失敗處理優(yōu)化

    • 通過(guò)rejectCalled標(biāo)記確保只處理第一個(gè)失敗的Promise
    • 后續(xù)的失敗會(huì)被忽略,符合Promise的狀態(tài)不可變特性
  4. 空數(shù)組處理

    • 若輸入數(shù)組為空,直接解析空數(shù)組resolve([]),與原生Promise.all([])行為一致

測(cè)試用例

測(cè)試1:所有Promise成功

const p1 = Promise.resolve(1);
const p2 = Promise.resolve(2);
Promise_all([p1, p2]).then(results => {
  console.log(results); // 輸出: [1, 2]
});

測(cè)試2:包含非Promise值

Promise_all([1, Promise.resolve(2), 3]).then(results => {
  console.log(results); // 輸出: [1, 2, 3]
});

測(cè)試3:Promise失敗

const p1 = Promise.resolve(1);
const p2 = Promise.reject(new Error("Fail"));
Promise_all([p1, p2]).catch(error => {
  console.error(error.message); // 輸出: "Fail"
});

測(cè)試4:空數(shù)組

Promise_all([]).then(results => {
  console.log(results); // 輸出: []
});

烏鴉的算法智慧

在卡拉的機(jī)器人軍團(tuán)控制程序中,類似Promise_all的機(jī)制用于協(xié)調(diào)多個(gè)機(jī)器人的動(dòng)作:

function coordinateRobots(robots) {
  return Promise_all(
    robots.map(robot => 
      robot.moveTo(targetPosition)
        .then(() => `Robot ${robot.id} arrived`)
        .catch(err => `Robot ${robot.id} failed: ${err}`)
    )
  );
}

這種實(shí)現(xiàn)確保:

  1. 所有機(jī)器人動(dòng)作并行執(zhí)行
  2. 任何一個(gè)機(jī)器人失敗都會(huì)立即通知主控系統(tǒng)
  3. 最終結(jié)果按機(jī)器人原始順序返回狀態(tài)

就像烏鴉群協(xié)作時(shí)需要同步行動(dòng)一樣,Promise_all讓異步操作在保持獨(dú)立性的同時(shí),能以整體視角處理成功與失敗。這種“統(tǒng)一協(xié)調(diào),快速響應(yīng)”的機(jī)制,正是異步編程中處理復(fù)雜場(chǎng)景的核心智慧。 ?????

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容