【大前端系列19】JavaScript核心:Promise異步編程與async/await實踐

JavaScript核心:Promise異步編程與async/await實踐

系列: 「全棧進化:大前端開發完全指南」系列第19篇
核心: 深入理解Promise機制與async/await語法,掌握現代異步編程技術

📌 引言

在JavaScript的世界中,異步編程是無法回避的核心概念。從最早的回調函數,到Promise的出現,再到ES7中async/await語法的引入,JavaScript的異步編程模式經歷了顯著的演變。這些變化不僅提升了代碼的可讀性和可維護性,也讓復雜異步流程的控制變得更加直觀和優雅。

異步編程之所以重要,是因為JavaScript作為單線程語言,需要高效處理諸如網絡請求、文件讀寫、定時器等不阻塞主線程的操作。掌握現代異步編程技術,對構建響應式、高性能的Web應用至關重要。

本文將帶你:

  • 理解Promise的設計理念與內部實現原理
  • 掌握Promise鏈式調用與錯誤處理的最佳實踐
  • 深入理解async/await語法糖的本質
  • 探索Promise的高級應用模式與性能優化策略
  • 手寫Promise核心功能,加深理解
  • 通過實戰案例,應用所學知識解決實際問題

無論你是剛剛接觸Promise的新手,還是想深入理解異步編程原理的資深開發者,本文都將為你提供系統而深入的指導。

📌 Promise基礎

2.1 從回調地獄到Promise

在Promise出現之前,JavaScript處理異步操作主要依賴回調函數,這種方式在處理多層嵌套的異步操作時,會導致所謂的"回調地獄"(Callback Hell):

getData(function(data) {getMoreData(data, function(moreData) {getEvenMoreData(moreData, function(evenMoreData) {getFinalData(evenMoreData, function(finalData) {// 終于拿到最終數據,但代碼已經深度嵌套console.log('Got the final data:', finalData);}, handleError);}, handleError);}, handleError);
}, handleError);

這種代碼不僅難以閱讀和維護,錯誤處理也變得復雜。Promise通過提供更結構化的方式來處理異步操作,解決了這些問題:

getData().then(data => getMoreData(data)).then(moreData => getEvenMoreData(moreData)).then(evenMoreData => getFinalData(evenMoreData)).then(finalData => {console.log('Got the final data:', finalData);}).catch(error => {// 統一處理錯誤handleError(error);});

2.2 Promise的狀態與生命周期

Promise是一個代表異步操作最終完成或失敗的對象。它有三種狀態:

  1. pending(進行中):初始狀態,既不是成功也不是失敗
  2. fulfilled(已成功):操作成功完成
  3. rejected(已失敗):操作失敗

Promise狀態的轉換是單向的,一旦從pending轉變為fulfilled或rejected,狀態就不再改變。這種特性確保了Promise的穩定性和可預測性。

Promise狀態轉換

2.3 Promise的基本用法

Promise構造函數接收一個執行器函數,該函數接受兩個參數:resolvereject

const promise = new Promise((resolve, reject) => {// 異步操作if (/* 操作成功 */) {resolve(value); // 成功,傳遞結果} else {reject(error); // 失敗,傳遞錯誤}
});promise.then(value => {// 處理成功結果}).catch(error => {// 處理錯誤}).finally(() => {// 無論成功失敗都會執行});

Promise提供了以下核心方法:

  • then(onFulfilled, onRejected):注冊成功和失敗回調
  • catch(onRejected):注冊失敗回調,相當于then(null, onRejected)
  • finally(onFinally):注冊一個總是會執行的回調,無論Promise成功或失敗

2.4 手寫簡易Promise實現

為了深入理解Promise的工作原理,我們可以實現一個符合Promises/A+規范的簡易版Promise:

class MyPromise {static PENDING = 'pending';static FULFILLED = 'fulfilled';static REJECTED = 'rejected';constructor(executor) {this.status = MyPromise.PENDING;this.value = undefined;this.reason = undefined;this.onFulfilledCallbacks = [];this.onRejectedCallbacks = [];const resolve = value => {if (this.status === MyPromise.PENDING) {this.status = MyPromise.FULFILLED;this.value = value;this.onFulfilledCallbacks.forEach(callback => callback(this.value));}};const reject = reason => {if (this.status === MyPromise.PENDING) {this.status = MyPromise.REJECTED;this.reason = reason;this.onRejectedCallbacks.forEach(callback => callback(this.reason));}};try {executor(resolve, reject);} catch (error) {reject(error);}}then(onFulfilled, onRejected) {onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason };// 創建新的Promise以支持鏈式調用const promise2 = new MyPromise((resolve, reject) => {if (this.status === MyPromise.FULFILLED) {setTimeout(() => {try {const x = onFulfilled(this.value);this.resolvePromise(promise2, x, resolve, reject);} catch (error) {reject(error);}}, 0);}if (this.status === MyPromise.REJECTED) {setTimeout(() => {try {const x = onRejected(this.reason);this.resolvePromise(promise2, x, resolve, reject);} catch (error) {reject(error);}}, 0);}if (this.status === MyPromise.PENDING) {this.onFulfilledCallbacks.push(value => {setTimeout(() => {try {const x = onFulfilled(value);this.resolvePromise(promise2, x, resolve, reject);} catch (error) {reject(error);}}, 0);});this.onRejectedCallbacks.push(reason => {setTimeout(() => {try {const x = onRejected(reason);this.resolvePromise(promise2, x, resolve, reject);} catch (error) {reject(error);}}, 0);});}});return promise2;}catch(onRejected) {return this.then(null, onRejected);}// 處理Promise解析過程resolvePromise(promise, x, resolve, reject) {if (promise === x) {reject(new TypeError('Chaining cycle detected for promise'));return;}let called = false;if (x !== null && (typeof x === 'object' || typeof x === 'function')) {try {const then = x.then;if (typeof then === 'function') {then.call(x,value => {if (called) return;called = true;this.resolvePromise(promise, value, resolve, reject);},reason => {if (called) return;called = true;reject(reason);});} else {resolve(x);}} catch (error) {if (called) return;called = true;reject(error);}} else {resolve(x);}}// 靜態方法static resolve(value) {return new MyPromise(resolve => resolve(value));}static reject(reason) {return new MyPromise((_, reject) => reject(reason));}
}

上面的實現包含了Promise的核心功能:

  • 三種狀態及狀態轉換
  • 異步支持和回調隊列
  • then方法的鏈式調用
  • 處理返回值和異常
  • 基本的靜態方法

2.5 Promise的微任務特性

Promise的回調是被推入微任務隊列(Microtask Queue)執行的,而不是宏任務隊列。這一點在處理異步操作順序時非常重要:

console.log('1. 同步代碼開始');setTimeout(() => {console.log('2. 宏任務(setTimeout)');
}, 0);Promise.resolve().then(() => {console.log('3. 微任務(Promise.then)');
});console.log('4. 同步代碼結束');// 輸出順序:
// 1. 同步代碼開始
// 4. 同步代碼結束
// 3. 微任務(Promise.then)
// 2. 宏任務(setTimeout)

微任務隊列的特性使得Promise可以在當前事件循環結束、下一個宏任務開始之前執行,這為異步操作提供了更好的實時性和可預測性。

📌 Promise進階

3.1 Promise鏈式調用深入解析

Promise的鏈式調用是其最強大的特性之一。每次調用then()方法都會返回一個新的Promise對象,而不是原來的Promise:

const promise = new Promise((resolve, reject) => {resolve(1);
});const promise2 = promise.then(value => {console.log(value); // 1return value + 1;
});const promise3 = promise2.then(value => {console.log(value); // 2return value + 1;
});promise3.then(value => {console.log(value); // 3
});// promise !== promise2 !== promise3

理解鏈式調用的數據流轉和異常傳遞機制是掌握Promise的關鍵:

  1. 返回值傳遞:一個Promise的then方法返回的值會被傳遞給下一個then方法
  2. Promise的傳遞:如果返回另一個Promise,將等待該Promise解決并傳遞其結果
  3. 異常冒泡:鏈中任何一環拋出的錯誤都會被后續的catch捕獲
  4. 錯誤恢復catch之后可以繼續then,實現錯誤恢復機制
fetchUser().then(user => {if (!user.isActive) {// 拋出錯誤,將跳過后續的then,直接進入catchthrow new Error('User not active');}return fetchUserPosts(user.id);}).then(posts => {// 處理文章return processUserPosts(posts);}).catch(error => {// 統一處理前面所有可能的錯誤console.error('Error:', error);// 返回一個默認值或新的Promise,繼續鏈式調用return { posts: [] };}).then(result => {// 錯誤處理后的恢復流程console.log('Final result:', result);});

3.2 Promise組合器:Promise.all、Promise.race、Promise.allSettled、Promise.any

Promise提供了多種組合方法,用于處理多個Promise的協作:

Promise.all(iterable)

等待所有Promise完成,或有一個被拒絕:

const promises = [fetch('/api/users'),fetch('/api/posts'),fetch('/api/comments')
];Promise.all(promises).then(responses => {// 所有請求都成功完成return Promise.all(responses.map(res => res.json()));}).then(data => {const [users, posts, comments] = data;// 使用獲取的數據console.log('Users:', users);console.log('Posts:', posts);console.log('Comments:', comments);}).catch(error => {// 只要有一個promise被拒絕,就會執行到這里console.error('Error:', error);});
Promise.race(iterable)

返回最先完成(無論成功或失敗)的Promise的結果:

// 實現請求超時
function fetchWithTimeout(url, timeout) {const fetchPromise = fetch(url);const timeoutPromise = new Promise((_, reject) => {setTimeout(() => reject(new Error('Request timed out')), timeout);});return Promise.race([fetchPromise, timeoutPromise]);
}fetchWithTimeout('/api/data', 5000).then(response => response.json()).then(data => console.log('Data:', data)).catch(error => console.error('Error:', error));
Promise.allSettled(iterable)

等待所有Promise完成(無論成功或失敗):

const promises = [fetch('/api/users').then(res => res.json()),fetch('/api/nonexistent').then(res => res.json()),fetch('/api/posts').then(res => res.json())
];Promise.allSettled(promises).then(results => {results.forEach((result, index) => {if (result.status === 'fulfilled') {console.log(`Promise ${index} succeeded with:`, result.value);} else {console.log(`Promise ${index} failed with:`, result.reason);}});// 篩選成功的結果const successfulResults = results.filter(result => result.status === 'fulfilled').map(result => result.value);return successfulResults;});
Promise.any(iterable)

返回第一個成功的Promise,如果都失敗則返回AggregateError:

const mirrors = ['https://mirror1.example.com/file','https://mirror2.example.com/file','https://mirror3.example.com/file'
];Promise.any(mirrors.map(url => fetch(url))).then(firstSuccessfulResponse => {console.log('Downloaded from first available mirror');return firstSuccessfulResponse.blob();}).catch(error => {console.error('All downloads failed:', error);});

3.3 Promise錯誤處理最佳實踐

Promise的錯誤處理需要特別注意,因為忽略錯誤可能導致靜默失敗:

// 錯誤的做法:未捕獲Promise拒絕
fetch('/api/data').then(response => {if (!response.ok) {throw new Error(`HTTP error! status: ${response.status}`);}return response.json();}).then(data => {console.log('Data:', data);});// 沒有catch,如果發生錯誤,將被吞沒或觸發未捕獲的Promise拒絕

以下是一些Promise錯誤處理的最佳實踐:

  1. 始終添加catch處理器
promiseFunction().then(result => {// 處理結果}).catch(error => {// 處理錯誤console.error('Error:', error);});
  1. 在Promise鏈的末尾使用單一catch
fetchData().then(processData).then(saveData).then(notifyUser).catch(error => {// 統一處理任何步驟的錯誤handleError(error);});
  1. 區分不同的錯誤類型
fetchData().then(data => {// 處理數據}).catch(error => {if (error instanceof NetworkError) {// 處理網絡錯誤} else if (error instanceof ValidationError) {// 處理驗證錯誤} else {// 處理其他錯誤throw error; // 如果不能處理,可以重新拋出}});
  1. 使用finally進行清理
showLoadingIndicator();fetchData().then(data => {displayData(data);}).catch(error => {showErrorMessage(error);}).finally(() => {// 無論成功或失敗,都會執行hideLoadingIndicator();});
  1. 處理未捕獲的Promise拒絕
window.addEventListener('unhandledrejection', event => {console.error('Unhandled promise rejection:', event.reason);// 可以進行全局錯誤處理event.preventDefault(); // 防止默認處理
});

3.4 Promise性能優化

在使用Promise進行復雜異步操作時,以下優化策略可以提高應用性能:

  1. 避免Promise嵌套:使用鏈式調用而不是嵌套
// 不好的實踐
fetch('/api/user').then(response => response.json()).then(user => {fetch(`/api/posts?userId=${user.id}`).then(response => response.json()).then(posts => {// 處理文章});});// 優化后
fetch('/api/user').then(response => response.json()).then(user => fetch(`/api/posts?userId=${user.id}`)).then(response => response.json()).then(posts => {// 處理文章});
  1. 合理使用Promise.all進行并行請求
// 串行請求(較慢)
async function fetchAllData() {const userData = await fetchUser();const postsData = await fetchPosts();const commentsData = await fetchComments();return { userData, postsData, commentsData };
}// 并行請求(較快)
async function fetchAllData() {const [userData, postsData, commentsData] = await Promise.all([fetchUser(),fetchPosts(),fetchComments()]);return { userData, postsData, commentsData };
}
  1. 優化Promise鏈中的計算密集型操作
fetchLargeDataSet().then(data => {// 計算密集型操作可能阻塞UIreturn processLargeData(data);}).then(result => {displayResult(result);});// 優化:使用Web Worker處理計算密集型任務
fetchLargeDataSet().then(data => {return new Promise(resolve => {const worker = new Worker('data-processor.js');worker.postMessage(data);worker.onmessage = e => {resolve(e.data);worker.terminate();};});}).then(result => {displayResult(result);});
  1. 避免不必要的Promise創建
// 不必要的Promise封裝
function getValue() {return new Promise(resolve => {resolve(42); // 直接返回值的情況});
}// 優化:使用Promise.resolve
function getValue() {return Promise.resolve(42);
}// 對于已經是Promise的值,不需要再次包裝
function processValue(value) {// 不好的做法return new Promise((resolve, reject) => {value.then(resolve).catch(reject);});// 更好的做法: 直接返回Promisereturn value;
}
  1. 使用Promise池控制并發數量
async function promisePool(promiseFns, poolLimit) {const results = [];const executing = new Set();async function executePromise(promiseFn, index) {const promise = promiseFn();executing.add(promise);try {const result = await promise;results[index] = result;} catch (error) {results[index] = error;} finally {executing.delete(promise);}}for (let i = 0; i < promiseFns.length; i++) {if (executing.size >= poolLimit) {await Promise.race(executing);}executePromise(promiseFns[i], i);}return Promise.all(results);
}// 使用示例
const urls = ['url1', 'url2', ..., 'url100'];
const promiseFns = urls.map(url => () => fetch(url));promisePool(promiseFns, 5) // 最多同時執行5個請求.then(results => {console.log('All requests completed');});

📌 async/await詳解

4.1 async/await的基本用法

async/await是ES7中引入的一種異步編程語法,它基于Promise,提供了更簡潔、直觀的異步代碼編寫方式:

async function fetchData() {try {const response = await fetch('/api/data');const data = await response.json();return data;} catch (error) {console.error('Error:', error);return null;}
}fetchData().then(data => {console.log('Data:', data);}).catch(error => {console.error('Error:', error);});

4.2 async/await的錯誤處理

async/await語法中,錯誤處理可以通過try/catch塊來實現:

async function fetchData() {try {const response = await fetch('/api/data');const data = await response.json();return data;} catch (error) {console.error('Error:', error);return null;}
}fetchData().then(data => {console.log('Data:', data);}).catch(error => {console.error('Error:', error);});

4.3 async/await的并發控制

async/await語法可以很方便地實現并發控制,例如:

async function fetchAllData() {const [userData, postsData, commentsData] = await Promise.all([fetch('/api/users').then(res => res.json()),fetch('/api/posts').then(res => res.json()),fetch('/api/comments').then(res => res.json())]);return { userData, postsData, commentsData };
}fetchAllData().then(data => {console.log('Users:', data.userData);console.log('Posts:', data.postsData);console.log('Comments:', data.commentsData);}).catch(error => {console.error('Error:', error);});

📌 異步函數實戰

5.1 異步函數與Promise的結合

async/await語法可以與Promise無縫結合,例如:

async function fetchData() {try {const response = await fetch('/api/data');const data = await response.json();return data;} catch (error) {console.error('Error:', error);return null;}
}fetchData().then(data => {console.log('Data:', data);}).catch(error => {console.error('Error:', error);});

5.2 異步函數與生成器的結合

async/await語法可以與生成器函數結合使用,例如:

async function* fetchData() {try {const response = await fetch('/api/data');const data = await response.json();yield data;} catch (error) {console.error('Error:', error);return null;}
}const dataIterator = fetchData();dataIterator.next().then(result => {if (!result.done) {console.log('Data:', result.value);}}).catch(error => {console.error('Error:', error);});

📌 總結與展望

6.1 異步編程范式的演進

JavaScript異步編程經歷了幾個主要階段的演進:

  1. 回調函數:最早的異步處理方式,簡單但容易形成回調地獄
  2. Promise:引入了更結構化的異步處理方案,支持鏈式調用和更好的錯誤處理
  3. Generators:允許暫停和恢復函數執行,為異步編程提供了新思路
  4. async/await:在Promise基礎上提供更簡潔、直觀的語法,使異步代碼更接近同步風格

這一演進過程體現了JavaScript作為一門語言在處理異步操作方面的不斷成熟和優化。

6.2 核心要點回顧

通過本文,我們深入了解了Promise和async/await的工作原理和最佳實踐:

  1. Promise的核心機制:狀態轉換、鏈式調用、錯誤傳播
  2. Promise的高級應用:組合器方法、錯誤處理、性能優化
  3. async/await的工作原理:基于Promise和生成器的語法糖
  4. async/await的最佳實踐:錯誤處理、并發控制、陷阱避免
  5. 實戰應用:構建可靠的數據服務和任務管理系統

6.3 未來發展趨勢

異步編程領域還在不斷發展,以下是一些值得關注的趨勢:

  1. 響應式編程:通過Observable等模式處理數據流和事件
  2. 并發原語:SharedArrayBuffer、Atomics等提供更底層的并發控制
  3. Worker線程:Web Workers和Worker Threads (Node.js)提供真正的多線程能力
  4. 異步迭代器for await...of語法用于處理異步數據流
  5. 頂層await:在模塊頂層使用await,無需async函數包裝

6.4 應用建議與最佳實踐總結

在實際開發中,我們推薦以下最佳實踐:

  1. 優先使用async/await處理主要業務邏輯,代碼更清晰易讀
  2. 善用Promise.all等方法進行并行處理,提高性能
  3. 始終添加完善的錯誤處理,避免未捕獲的Promise拒絕
  4. 考慮請求超時和重試機制,提升應用可靠性
  5. 合理使用緩存,減少不必要的網絡請求
  6. 注意內存泄漏問題,不要在Promise鏈中持有不再需要的大對象引用
  7. 使用合適的抽象層,如本文的數據服務模塊,提高代碼可維護性

掌握這些現代JavaScript異步編程技術,將幫助你構建更高效、可靠和易維護的Web應用。

參考資料

  1. MDN Web Docs - Promise
  2. MDN Web Docs - async function
  3. JavaScript Info - Promise
  4. JavaScript Info - Async/await
  5. Promises/A+ 規范
  6. You Don’t Know JS: Async & Performance

作者: 秦若宸 - 全棧工程師,擅長前端技術與架構設計,個人簡歷

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/74966.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/74966.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/74966.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

如何排查java程序的宕機和oom?如何解決宕機和oom?

排查oom 用jmap生成我們的堆空間的快照Heap Dump&#xff08;堆轉儲文件&#xff09;&#xff0c;來分析我們的內存占用 用可視化工具&#xff0c;例如java中的jhat分析Heap Dump文件 &#xff0c;它分析完會通過一個瀏覽器打開一個可視化頁面展示分析結果 根據oom的類型來調…

什么是 OLAP 數據庫?企業如何選擇適合自己的分析工具

引言&#xff1a;為什么企業需要 OLAP 數據庫&#xff1f; 你是否曾經經歷過這樣的場景&#xff1a; 市場部門急需一份用戶行為分析報告&#xff0c;數據團隊告訴你&#xff1a;“數據太大了&#xff0c;報表要跑 4 個小時”&#xff1b;業務負責人在會議中提出一個臨時性分析…

測試:認識Bug

目錄 一、軟件測試的生命周期 二、bug 一、軟件測試的生命周期 軟件測試貫穿于軟件的生命周期。 需求分析&#xff1a; ???度&#xff1a;軟件需求是否合理 技術?度&#xff1a;技術上是否可?&#xff0c;是否還有優化空間 測試?度&#xff1a;是否存在業務邏輯錯誤、…

綜合實驗2

1、sw1和sw2之間互為備份 [sw1]interface Eth-Trunk 0 &#xff08;創建聚合接口&#xff09; [sw1-Eth-Trunk0]trunkport g0/0/1 &#xff08;將物理接口劃入到聚合接口中&#xff09; [sw1-Eth-Trunk0]trunkport g0/0/2 [sw2]interface Eth-Trunk 0 [sw2-Eth-T…

【ArcGIS】ArcGIS10.6徹底卸載和ArcGIS10.2安裝全過程

卸載python3后,解決了ArcGIS與python3沖突問題后,軟件可以正常打開使用了 但是還是出現了問題 用ArcGIS 進行空間分析時,中間操作沒有任何報錯和問題,但是就是沒有運行結果 在別人的軟件上操作一遍可以出現運行結果 關閉確有這個,但真的不是我給它的運行時間不夠,反反復復試…

Django之旅:第五節--Mysql數據庫操作(一)

Django開發操作數據庫更簡單&#xff0c;內部提供了ORM框架 一、安裝第三方模塊 pip install mysqlclient注&#xff1a;最新的django框架需要使用mysqlclient模塊&#xff0c;之前pymysql模塊與django框架有編碼兼容問題。 二、ORM 1、ORM可以幫助我們做兩件事&#xff1a;…

docker部署mongodb數據庫

1、下載 MongoDB 鏡像 使用Docker部署MongoDB 之前&#xff0c;我們需要從 Docker Hub 上下載 MongoDB 鏡像。這里我們下載最新版本的 MongoDB 鏡像&#xff0c;使用以下命令進行下載&#xff1a; docker pull mongo:latest 下載完成后&#xff0c;我們就擁有了最新版本的 Mon…

Enhanced PEC-YOLO:電力施工場景安全裝備檢測的輕量化算法解析

目錄 一、核心概述 二、核心創新點 1. ?C2F_Faster_EMA模塊 2. ?SPPF_CPCA多尺度模塊 3. ?BiFPN頸部網絡

【人工智能】解鎖大模型潛力:Ollama 與 DeepSeek 的分布式推理與集群部署實踐

《Python OpenCV從菜鳥到高手》帶你進入圖像處理與計算機視覺的大門! 解鎖Python編程的無限可能:《奇妙的Python》帶你漫游代碼世界 隨著大語言模型(LLM)的快速發展,其推理能力在自然語言處理、代碼生成等領域展現出巨大潛力。然而,單機部署難以滿足高并發、低延遲的需…

RTMP推流服務器nginx在linux上的編譯部署

RTMP&#xff08;Real-Time Messaging Protocol&#xff09;推流確實需要服務器支持?。RTMP推流服務器的主要功能是接收來自推流客戶端的數據流&#xff0c;對其進行處理和轉發。服務器會根據RTMP協議與客戶端建立連接&#xff0c;處理推流數據&#xff08;如轉碼、錄制等&…

PyQt6實例_批量下載pdf工具_主線程停止線程池

目錄 前置&#xff1a; 代碼&#xff1a; 視頻&#xff1a; 前置&#xff1a; 1 本系列將以 “PyQt6實例_批量下載pdf工具”開頭&#xff0c;放在 【PyQt6實例】 專欄 2 本系列涉及到的PyQt6知識點&#xff1a; 線程池&#xff1a;QThreadPool,QRunnable&#xff1b; 信號與…

Tomcat生產服務器性能優化

試想以下這個情景&#xff1a;你已經開發好了一個程序&#xff0c;這個程序的排版很不錯&#xff0c;而且有著最前沿的功能和其他一些讓你這程序增添不少色彩的元素。可惜的是&#xff0c;程序的性能不怎么地。你也十分清楚&#xff0c;若現在把這款產品退出市場&#xff0c;肯…

正則表達式-筆記

文章目錄 一、正則表達式二、正則表達式的基本語法字符類普通字符非打印字符特殊字符 量詞限定符錨點修飾符&#xff08;標記&#xff09; 三、在 Python 中使用正則表達式簡單搜索提取信息替換文本 參考 從驗證用戶輸入&#xff0c;到從大量文本中提取特定信息&#xff0c;再到…

Qwen-0.5b linux部署

參考鏈接 https://blog.csdn.net/imwaters/article/details/145489543 https://modelscope.cn/models/modelscope/ollama-linux 1. ollama安裝 # 安裝ModelScope工具包&#xff0c;用于下載和管理AI模型 pip install modelscope# 下載Ollama的Linux版本安裝包 # --model 指定…

【深度學習】GAN生成對抗網絡:原理、應用與發展

GAN生成對抗網絡&#xff1a;原理、應用與發展 文章目錄 GAN生成對抗網絡&#xff1a;原理、應用與發展1. 引言2. GAN的基本原理2.1 核心思想2.2 數學表達2.3 訓練過程 3. GAN的主要變體3.1 DCGAN (Deep Convolutional GAN)3.2 CGAN (Conditional GAN)3.3 CycleGAN3.4 StyleGAN…

【AI速讀】CNN圖像處理單元的形式化驗證方法

近年來,卷積神經網絡(CNN)在圖像處理和計算機視覺領域取得了巨大成功,如人臉識別、姿態估計等。然而,基于CNN的圖像處理單元設計復雜,驗證工作面臨巨大挑戰。傳統的仿真驗證方法難以覆蓋其龐大的配置空間,且耗時費力。本文將介紹一種創新的形式化驗證(Formal Verificat…

【新人系列】Golang 入門(八):defer 詳解 - 上

? 個人博客&#xff1a;https://blog.csdn.net/Newin2020?typeblog &#x1f4dd; 專欄地址&#xff1a;https://blog.csdn.net/newin2020/category_12898955.html &#x1f4e3; 專欄定位&#xff1a;為 0 基礎剛入門 Golang 的小伙伴提供詳細的講解&#xff0c;也歡迎大佬們…

鴻蒙開發:了解Canvas繪制

前言 本文基于Api13 系統的組件無法滿足我們的需求&#xff0c;這種情況下就不得不自己自定義組件&#xff0c;除了自定義組合組件&#xff0c;拓展組件&#xff0c;還有一種方式&#xff0c;那就是完全的自繪制組件&#xff0c;這種情況&#xff0c;常見的場景有&#xff0c;比…

【Linux筆記】進程間通信——命名管道

&#x1f525;個人主頁&#x1f525;&#xff1a;孤寂大仙V &#x1f308;收錄專欄&#x1f308;&#xff1a;Linux &#x1f339;往期回顧&#x1f339;&#xff1a;【Linux筆記】進程間通信——匿名管道||進程池 &#x1f516;流水不爭&#xff0c;爭的是滔滔不 一、命名管道…

Spring項目中使用EasyExcel實現Excel 多 Sheet 導入導出功能(完整版)

Excel 多 Sheet 導入導出功能完整實現指南 一、環境依賴 1. Maven 依賴 <!-- EasyExcel --> <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.3.2</version> </dependency>…