基于C++11手擼前端Promise及應用與優(yōu)勢
引言
在前端開發(fā)中,Promise 是處理異步操作的重要工具。它通過將異步操作封裝在 Promise 實例中,解決了傳統(tǒng)回調(diào)地獄的問題,提高了代碼的可讀性和可維護性。Promise 的概念并非前端獨有,在 C++11 標準中也引入了 std::promise,用于實現(xiàn)類似的功能。
本文將從一個手寫的 C++ Promise 實現(xiàn)(基于 C++11)出發(fā),分析其工作原理,并與 std::promise 進行對比,探討兩者的異同點以及適用場景。
前端Promise的應用與優(yōu)勢
常見應用場景
網(wǎng)絡請求
Promise 可以用于處理 AJAX 請求,簡化異步數(shù)據(jù)獲取的邏輯。
fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => {
console.log('獲取到數(shù)據(jù):', data);
})
.catch(error => {
console.error('請求失敗:', error);
});
定時器
Promise 還可以用于處理定時器,使代碼更加直觀。
function timeout(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}
timeout(1000)
.then(() => {
console.log('1秒后執(zhí)行');
});并發(fā)請求
使用 Promise.all 可以同時處理多個異步請求。
const promise1 = fetch('https://api.example.com/data1');
const promise2 = fetch('https://api.example.com/data2');
Promise.all([promise1, promise2])
.then(responses => {
const [data1, data2] = responses.map(response => response.json());
return Promise.all([data1, data2]);
})
.then(([data1, data2]) => {
console.log('兩個數(shù)據(jù)都獲取成功:', data1, data2);
})
.catch(error => {
console.error('至少一個請求失敗:', error);
});Promise 解決的問題
- 回調(diào)地獄:通過鏈式調(diào)用,Promise 解決了傳統(tǒng)回調(diào)嵌套導致的代碼難以閱讀和維護的問題【6†source】。
- 錯誤處理:Promise 提供了統(tǒng)一的錯誤處理機制,通過
catch方法可以集中處理所有異步操作中的錯誤【1†source】。 - 代碼可讀性:Promise 使得異步代碼的邏輯更加清晰,符合同步代碼的書寫習慣【6†source】。
- 并發(fā)控制:通過
Promise.all和Promise.race,可以方便地控制多個異步操作的執(zhí)行順序和結果【5†source】。
手寫 C++ Promise 實現(xiàn)
類結構與成員變量
template<typename Element>
class CProimse
{
private:
using Resolve = std::function<void(Element)>;
using Reject = std::function<void(const std::string&)>;
private:
Element m_element; /**< 異步操作的結果 */
std::string m_reason; /**< 拒絕的原因 */
CProimseState m_state; /**< 當前狀態(tài) */
std::list<Resolve> m_resolves; /**< 成功回調(diào)函數(shù)列表 */
std::list<Reject> m_rejects; /**< 失敗回調(diào)函數(shù)列表 */
public:
CProimse();
void reject(const std::string& reason);
void resolve(Element element);
void onCatch(const Reject& rej);
CProimse* then(const Resolve& res);
};Resolve和Reject:定義了成功和失敗回調(diào)函數(shù)的類型。m_element和m_reason:分別存儲 Promise 的結果和拒絕原因。m_state:表示 Promise 的當前狀態(tài),初始狀態(tài)為 PENDING。m_resolves和m_rejects:存儲注冊的成功和失敗回調(diào)函數(shù)列表。
構造函數(shù)
CProimse()
: m_state(CProimseState::PENDING)
{
}
- 作用:初始化 Promise 的狀態(tài)為 PENDING。
resolve 方法
void resolve(Element element)
{
m_element = element;
if (m_state == CProimseState::PENDING)
{
m_state = CProimseState::FULFILLED;
for (Resolve res : m_resolves)
{
res(element);
}
}
}
- 作用:將 Promise 的狀態(tài)設置為 FULFILLED,并執(zhí)行所有注冊的成功回調(diào)函數(shù)。
reject 方法
void reject(const std::string& reason)
{
m_reason = reason;
if (m_state == CProimseState::PENDING)
{
m_state = CProimseState::REJECTED;
for (Reject rej : m_rejects)
{
rej(reason);
}
}
}
- 作用:將 Promise 的狀態(tài)設置為 REJECTED,并執(zhí)行所有注冊的失敗回調(diào)函數(shù)。
then 方法
CProimse* then(const Resolve& res)
{
if (m_state == CProimseState::FULFILLED)
{
res(m_element);
}
else if (m_state == CProimseState::PENDING)
{
m_resolves.push_back(res);
}
return this;
}
- 作用:注冊一個成功回調(diào)函數(shù)。如果 Promise 已經(jīng)完成,則立即執(zhí)行回調(diào);否則,將回調(diào)添加到成功回調(diào)列表中。
onCatch 方法
void onCatch(const Reject& rej)
{
if (m_state == CProimseState::REJECTED)
{
rej(m_reason);
}
else if (m_state == CProimseState::PENDING)
{
m_rejects.push_back(rej);
}
}
- 作用:注冊一個失敗回調(diào)函數(shù)。如果 Promise 已經(jīng)被拒絕,則立即執(zhí)行回調(diào);否則,將回調(diào)添加到失敗回調(diào)列表中。
鏈式調(diào)用
通過 then 和 onCatch 方法,可以實現(xiàn)鏈式調(diào)用,使得異步操作的處理更加簡潔和直觀。
proimse->then([](int ele) -> void {
std::cout << ele << std::endl;
})->onCatch([](const std::string& reason) -> void {
std::cout << reason << std::endl;
});
使用示例
CProimse<int>* proimse = new CProimse<int>();
proimse->then([](int ele) -> void {
std::cout << ele << std::endl;
})->onCatch([](const std::string& reason) -> void {
std::cout << reason << std::endl;
});
proimse->reject("網(wǎng)絡異常!!!");std::promise與CProimse對比
1. 基礎功能對比
| 功能 | CProimse 實現(xiàn) | std::promise |
|---|---|---|
| 狀態(tài)管理 | 手動實現(xiàn) | 標準庫實現(xiàn) |
| 回調(diào)注冊與執(zhí)行 | 手動實現(xiàn) | 標準庫實現(xiàn) |
| 異步支持 | 需結合線程 | 內(nèi)置支持 |
| 鏈式調(diào)用 | 支持 | 不支持 |
2. 實現(xiàn)細節(jié)對比
(1) 狀態(tài)管理
CProimse:通過自定義枚舉CProimseState管理狀態(tài)。std::promise:狀態(tài)管理由標準庫實現(xiàn),用戶無需關注底層細節(jié)。
(2) 回調(diào)注冊與執(zhí)行
CProimse:手動維護回調(diào)隊列,通過then和onCatch方法注冊回調(diào)。std::promise:通過std::future與std::promise配合,回調(diào)通過future的get方法觸發(fā)。
(3) 異步支持
CProimse:需要結合std::thread或其他異步框架實現(xiàn)異步操作。std::promise:內(nèi)置支持異步操作,通常與std::async或std::thread結合使用。
(4) 鏈式調(diào)用
CProimse:支持鏈式調(diào)用,通過返回this實現(xiàn)。std::promise:不支持鏈式調(diào)用,無法直接鏈式注冊回調(diào)。
3. 代碼示例對比
(1)CProimse示例
CProimse<int>* proimse = new CProimse<int>();
proimse->then([](int ele) -> void {
std::cout << ele << std::endl;
})->onCatch([](const std::string& reason) -> void {
std::cout << reason << std::endl;
});
proimse->reject("網(wǎng)絡異常!!!");(2)std::promise示例
#include <future>
#include <thread>
#include <iostream>
int main()
{
std::promise<int> prom;
std::future<int> fut = prom.get_future();
// 異步操作
std::thread([&prom]() {
// 模擬網(wǎng)絡請求
std::this_thread::sleep_for(std::chrono::seconds(1));
prom.set_value(42);
}).detach();
// 注冊回調(diào)
fut.then([](std::future<int> fut) {
try {
int result = fut.get();
std::cout << "結果: " << result << std::endl;
} catch (const std::exception& e) {
std::cout << "錯誤: " << e.what() << std::endl;
}
});
// 主線程阻塞等待
std::this_thread::sleep_for(std::chrono::seconds(2));
return 0;
}4. 優(yōu)缺點分析
(1)CProimse
- 優(yōu)點:
- 代碼簡潔,易于理解。
- 支持鏈式調(diào)用,使用方式類似前端 Promise。
- 可以作為學習 Promise 實現(xiàn)原理的示例。
- 缺點:
- 不支持內(nèi)置異步操作,需要結合線程實現(xiàn)。
- 功能較為基礎,缺乏
std::promise的高級特性(如then的鏈式返回)。
(2)std::promise
- 優(yōu)點:
- 內(nèi)置異步支持,與
std::future配合使用,功能強大。 - 標準庫實現(xiàn),性能優(yōu)化和穩(wěn)定性有保障。
- 支持 C++11 及以上標準,兼容性好。
- 內(nèi)置異步支持,與
- 缺點:
- 使用方式較為復雜,缺乏鏈式調(diào)用的支持。
- 回調(diào)機制不夠靈活,無法像前端 Promise 那樣優(yōu)雅地處理異步流程。
總結與展望
通過手寫 CProimse,我們可以深入理解 Promise 的實現(xiàn)原理,包括狀態(tài)管理、回調(diào)注冊與執(zhí)行等核心機制。然而,在實際開發(fā)中,std::promise 仍然是更好的選擇,因為它提供了更強大的功能和更好的性能保障。
對于開發(fā)者來說,理解 std::promise 的工作原理以及其與手寫實現(xiàn)的異同點,有助于更好地選擇合適的工具來處理異步操作。同時,手寫實現(xiàn)雖然功能有限,但作為學習和探索的工具,仍然具有重要的價值。
希望本文能夠幫助讀者更好地理解 Promise 的實現(xiàn)原理,并在實際開發(fā)中做出更明智的選擇。
到此這篇關于基于C++11手擼前端Promise及應用與優(yōu)勢的文章就介紹到這了,更多相關C++ Promise內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
VSCode Linux的C++代碼格式化配置的實現(xiàn)
動格式化代碼容易出現(xiàn)錯誤,特別是當代碼量較大時,使用自動格式化可以減少這種錯誤的風險,本文主要介紹了VSCode Linux的C++代碼格式化配置的實現(xiàn),感興趣的可以了解一下2023-10-10
詳解如何實現(xiàn)C++虛函數(shù)調(diào)用匯編代碼
多態(tài)是C++中最重要的特性之一,對虛函數(shù)的調(diào)用在C++代碼中是隨處可見的,本篇文章我們詳細探討一下,感興趣的朋友快來看看吧2021-11-11

