node.js下when.js 的非同步程式設計實作_node.js
假設一個商業場景:
透過rss地址,取得rss並儲存於文件,rss地址保存於文件中。
完成該場景的業務需要完成3個任務:
1.從檔案讀取rss位址。
2.取得rss。
3.儲存於文件。
最後將這三個任務整合。
準備:
存放rss地址的文件,address.txt。
http://programmer.csdn.net/rss_programmer.html
任務1:
讀取rss位址檔案的內容並透過callback回傳。
var getRssAddress = function(path, callback) {
fs.readFile(path, {encoding: 'utf8'}, function (err, data) {
callback(err, data);
});
}
任務2:
透過rss位址get到rss,並透過callback回傳錯誤或資料。
var getRss = function(url, callback) {
var data = '';
http.get(url, function(res) {
res.on('data', function(chrunk) {
data = chrunk;
});
res.on('end', function() {
callback(null, data);
});
}).on('error', function(err) {
callback(err, null);
});
}
任務3:
將rss儲存於檔案並透過callback回傳錯誤。
var saveRss = function(data, callback) {
fs.writeFile('rss.txt', data, 'utf8', function(err) {
callback(err);
});
}
整合:
getRssAddress('address.txt', function(err, data) {
if(err) {
console.log(err);
return;
}
getRss(data, function(err, data) {
if(err) {
console.log(err);
return;
}
saveRss(data, function(err) {
if(err) console.log(err);
});
});
});
上面的程式碼是全非同步處理,使用最常見的callback處理非同步邏輯的返回,好處是標準寫法,大家都能容易接受;壞處是耦合性太強,處理異常麻煩,程式碼不直觀,特別是處理業務邏輯複雜和處理任務多的場景,層層的callback會讓人眼冒金星,程式碼難以維護。
Promise/A規範的實作之一when.js正是針對這樣的問題域。
讓我們來看看改造後的程式碼。
任務1:
var getRssAddress = function(path) {
var deferred = when.defer();
fs.readFile(path, {encoding: 'utf8'}, function (err, data) {
if (err) deferred.reject(err);
deferred.resolve(data);
});
return deferred.promise;
}
任務2:
var getRss = 函數(url) {
var deferred = when.defer();
var data = '';
http.get(url, 函數(res) {
res.on('data', function(chrunk) {
資料 = 區塊;
});
res.on('end', function() {
deferred.resolve(資料);
});
}).on('錯誤', 函數(err) {
deferred.reject(err);
});
返回 deferred.promise;
}
任務3:
var saveRss = 函數(data) {
var deferred = when.defer();
fs.writeFile('rss.txt', data, 'utf8', function(err) {
if(err) deferred.reject(err);
deferred.resolve();
});
回 deferred.promise;
}
整合:
getRssAddress('address.txt')
.then(getRss)
.then(saveRss)
.catch(函數(錯誤) {
console.log(錯誤);
});
解釋:
promise/A規範定義的「Deferred/Promise」模型就是「發布/訂閱者」模型,透過Deferred物件發布事件,可以是完成resolve事件,或是失敗reject事件;透過Promise物件回覆完成或失敗的訂閱。
在Promises/A規格中,每個任務都有透明狀態:預設(pending)、完成(fulfilled)、失敗(rejected)。
1.預設狀態可以單向轉移到完成,這個過程叫做resolve,對應的方法是deferred.resolve(promiseOrValue);
2.預設狀態還可以單向轉移到失敗,這個過程叫做reject,對應的方法是deferred.reject(reason);
3.狀態預設時,也可以透過deferred.notify(update)來宣告任務執行訊息,如執行進度;
4.狀態的轉移是瞬時的,一旦任務由初始的pending轉為其他狀態,就會進入到下一個任務的執行過程中。
按照上面的程式碼。
透過when.defer定義一個deferred物件。
var deferred = when.defer();
非同步資料獲取成功後,發布一個完成事件。
deferred.resolve(數據);
非同步資料獲取失敗後,發布一個失敗事件。
deferred.reject(err);
並返回Promise物件作為訂閱使用。
返回 deferred.promise;
訂閱是透過Promise物件的then方法進行完成/失敗/通知的訂閱。
getRssAddress('address.txt')
.then(getRss)
那麼有三個參數,分別是onFulfilled、onRejected、onProgress
promise.then(onFulfilled, onRejected, onProgress)
上一個任務被resolve(data),onFulfilled函數就會被觸發,data作為它的參數。
上一個任務被拒絕(原因),那麼onRejected就會被觸發,收到原因。
任何時候,onFulfilled和onRejected都只有其中一個可以被觸發,並且只觸發一次。
對於處理異常,when.js也提供了極為方便的方法,然後可以提交錯誤,多個任務串列執行時,我們可以只在最後一個then定義onRejected。也可以在最後一個then的後面呼叫catch函數捕捉任何一個任務的異常。
這樣寫法就簡單明了。
getRssAddress('address.txt')
.then(getRss)
.then(saveRss)
.catch(函數(錯誤) {
console.log(錯誤);
});
Promise 為非同步程式設計帶來了巨大的方便,可以讓我們專注於單一任務的實現而不是瀑布金字塔厄運,除了以上程式碼的基本使用,when.js 提供的功能顯然不止本文提到的這些,具體參考官方API。

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

摘要:C++中的非同步程式設計允許多工處理,無需等待耗時操作。使用函數指標建立指向函數的指標。回調函數在非同步操作完成時被呼叫。 boost::asio等函式庫提供非同步程式支援。實戰案例示範如何使用函數指標和boost::asio實現非同步網路請求。

隨著Web應用程式變得越來越複雜,程式設計師不得不採用非同步程式來處理大量請求和I/O操作。 PHP:HypertextPreprocessor也不例外。為了滿足這項需求,ReactPHP已成為目前最受歡迎的PHP非同步程式設計框架之一。在本文中,將討論如何在PHP中使用ReactPHP進行非同步程式設計。 1.ReactPHP簡介ReactPHP是基於事件驅動編程

JavaScript函數非同步程式設計:處理複雜任務的必備技巧引言:在現代前端開發中,處理複雜任務已經成為了必不可少的一部分。而JavaScript函數非同步程式設計技巧則是解決這些複雜任務的關鍵。本文將介紹JavaScript函數非同步程式設計的基本概念和常用的實作方法,並提供具體的程式碼範例,幫助讀者更好地理解和使用這些技巧。一、非同步程式設計的基本概念在傳統的同步程式設計中,程式碼按

如何在PHP中實現非同步訊息處理引言:在現代的Web應用程式中,非同步訊息處理變得越來越重要。非同步訊息處理可以提高系統的效能和可擴展性,並改善使用者體驗。 PHP作為一種常用的伺服器端程式語言,也可以透過一些技術來實現非同步訊息處理。在本文中,我們將介紹一些PHP中實作非同步訊息處理的方法,並提供程式碼範例。使用訊息佇列訊息佇列是一種解耦系統元件的方式,它允許不同的元件在

Java框架非同步程式設計中常見的3個問題和解決方案:回呼地獄:使用Promise或CompletableFuture以更直覺的風格管理回呼。資源競爭:使用同步原語(如鎖)保護共享資源,並考慮使用執行緒安全性集合(如ConcurrentHashMap)。未處理異常:明確處理任務中的異常,並使用異常處理框架(如CompletableFuture.exceptionally())處理異常。

深入理解PHP8的新特性:如何有效地使用非同步程式設計和程式碼? PHP8是PHP程式語言的最新主要版本,帶來了許多令人興奮的新功能和改進。其中最突出的特性之一是對非同步程式設計的支援。非同步程式設計可讓我們在處理並發任務時提高效能和回應能力。本文將深入探討PHP8的非同步程式設計特性,並介紹如何有效率地使用它們。首先,讓我們來了解一下什麼是非同步程式設計。在傳統的同步程式設計模型中,程式碼依照線性的順

Go框架利用Go的並發和非同步特性提供高效處理並發和非同步任務的機制:1.透過Goroutine實現並發,允許同時執行多個任務;2.透過通道實現非同步編程,在不阻塞主執行緒的情況下執行任務;3.適用於實戰場景,如並發處理HTTP請求、非同步取得資料庫資料等。

1.為什麼要使用非同步程式設計?傳統程式設計使用阻塞式I/O,這表示程式會等待某個操作完成,然後才能繼續執行。這對於處理單一任務可能很有效,但對於處理大量任務時,可能會導致程式變慢。非同步程式設計則打破了傳統阻塞式I/O的限制,它使用非阻塞式I/O,這意味著程式可以將任務分發到不同的執行緒或事件循環中執行,而無需等待任務完成。這允許程式同時處理多個任務,提高程式的效能和效率。 2.python非同步程式設計的基礎Python非同步程式設計的基礎是協程和事件循環。協程是允許函數在暫停和恢復之間切換的函數。事件循環則負責調度
