搜尋
首頁web前端js教程NodeJS中利用Promise來封裝非同步函數_node.js

 在寫Node.js的過程中,連續的IO操作可能會導致“金字塔噩夢”,回調函數的多重嵌套讓代碼變的難以維護,利用CommonJs的Promise來封裝異步函數,使用統一的鏈式API來擺脫多重回呼的惡夢。

  Node.js提供的非阻塞IO模型允許我們利用回調函數的方式處理IO操作,但是當需要連續的IO操作時,你的回調函數會多重嵌套,程式碼很不美觀,而且不易維護,而且可能會有許多錯誤處理的重複程式碼,也就是所謂的「Pyramid of Doom」。

複製程式碼 程式碼如下:

step1(function (value1) {
    step2(value1, function(value2) {
        step3(value2, function(value3) {
            step4(value3, function(value4) {
                // Do something with value4
            });
        });
    });
});

  這其實就是Node.js的Control flow的問題,對於這個問題,解決方案都許多,比如利用async,或者eventProxy等,不過本文的主題是利用CommonJs規範中對Promise來解決這個問題。

什麼是Promise?

  CommonJs的Promise規範有許多種,我們一般討論的是Promise/A 規範,它定義了Promise的基本行為。

  Promise是一個對象,它通常代表一個在未來可能完成的非同步操作。這個操作可能成功也可能失敗,所以一個Promise物件一般有3個狀態:Pending,Fulfilled,Rejected。分別代表未完成、成功完成和操作失敗。一旦Promise物件的狀態從Pending變成Fulfilled或Rejected任一個,它的狀態都沒有辦法再被改變。

  一個Promise物件通常會有一個then方法,這個方法讓我們可以去操作未來可能成功後回傳的值或是失敗的原因。這個then方法是這樣子的:

promise.then(onFulfilled, onRejected)
顯而易見的是,then方法接受兩個參數,它們通常是兩個函數,一個是用來處理操作成功後的結果的,另一個是用來處理操作失敗後的原因的,這兩個函數的第一個參數分別是成功後的結果和失敗的原因。如果傳給then方法的不是一個函數,那麼這個參數就會被忽略。

  then方法的回傳值是一個Promise對象,這一個特點允許我們鍊式呼叫then來達到控制流程的效果。這裡有許多細節上的問題,例如值的傳遞或錯誤處理等。 Promise的規範是這樣定義的:

onFulfilled或onRejected函數的回傳值不是Promise對象,則該值將會作為下一個then方法中onFulfilled的第一個參數,如果傳回值是一個Promise對象,怎麼then方法的回傳值就是該Promise對象
onFulfilled或onRejected函數中如果有異常拋出,則該then方法的回傳的Promise物件狀態轉為Rejected,如果該Promise物件呼叫then,則Error物件會作為onRejected函數的第一個參數
如果Promise狀態變成Fulfilled而在then方法中沒有提供onFulfilled函數,則then方法傳回的Promise物件狀態變成Fulfilled且成功的結果為上一個Promise的結果,Rejected同理。
  補充一句,onFulfilled和onRejected都是非同步執行的。

規範的實作:q

  上面講的是Promise的規範,而我們需要的是它的實現,q是一個對Promise/A 有著較好實現規範的函式庫。

  首先我們需要創建一個Promise對象,關於Promise對象創建的規範在Promise/B中,這裡不做詳細的解釋,直接上代碼。

複製程式碼 程式碼如下:

    function(flag){
        var defer = q.defer();
        fs.readFile("a.txt", function(err, data){
        if(err) defer.reject(err);
            else defer.resolve(data);
            });
            return defer.promise;
    }

  多數Promise的實作在Promise的建立上大同小異,透過建立一個具有promise屬性的defer對象,如果成功取得到值則呼叫defer.resolve(value),如果失敗,則呼叫defer.reject(reason),最後回傳defer的promise屬性即可。這個過程可以理解為呼叫defer.resolve將Promise的狀態變成Fulfilled,呼叫defer.reject將Promise的狀態變成Rejected。

  在面對一系列連續的非同步方法時,怎麼利用Promise寫出漂亮的程式碼呢?看下下面的例子。

複製程式碼 程式碼如下:

    promise0.then(function(result){
        // dosomething
        return result;
    }).then(function(result) {
        // dosomething
        return promise1;   
    }).then(function(result) {
        // dosomething
    }).catch(function(ex) {
        console.log(ex);
    }).finally(function(){
        console.log("final");
    });

  在上面的程式碼中,then方法只接受OnFulfilled,而catch方法實際上就是then(null, OnRejected),這樣的話只要一系列非同步方法只要總是成功回傳值的,那麼程式碼就會瀑布式的向下運行,如果其中任一個非同步方法失敗或發生異常,那麼根據CommonJs的Promise規範,將執行catch中的function。 q也提供了finally方法,從字面上也很好理解,就是不論resolve還是reject,最後都會執行finally中的function。

  看起來似乎不錯,程式碼更以維護且美觀了,那麼如果希望並發呢?

複製程式碼 程式碼如下:

     q.all([promise0, promise1, promise2]).spread(function(val0, val1, val2){
                    console.log(arguments);
                }).then(function(){
                    console.log("done");
                }).catch(function(err){
                    console.log(err);
                });

  q也為並發提供了api,呼叫all方法並傳遞一個Promise數組即可繼續使用then的鍊式風格。還有像q.nfbind等可以將Node.js的原生API轉換成Promise來統一程式碼格式也是挺好的。更多api在這裡就不一一詳述了。

結論

  本文主要介紹透過使用Promise來解決Node.js控制流問題,但Promise也可同樣應用於前端,EMCAScript6已經提供了原生的API支援。需要指出的是Promise並不是唯一的解決方案,async也是一個很好的選擇,並且提供更友好的並發控制API,不過我覺得Promise在封裝具有非同步方法的函數時更具優勢。

好了,本文就先到這裡了,希望對大家能夠有所幫助。

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
在Vue应用中遇到Uncaught (in promise) TypeError怎么办?在Vue应用中遇到Uncaught (in promise) TypeError怎么办?Jun 25, 2023 pm 06:39 PM

Vue是一款流行的前端框架,在开发应用时经常会遇到各种各样的错误和问题。其中,Uncaught(inpromise)TypeError是常见的一种错误类型。在本篇文章中,我们将探讨它的产生原因和解决方法。什么是Uncaught(inpromise)TypeError?Uncaught(inpromise)TypeError错误通常出现在

言出必行:兑现承诺的好处和坏处言出必行:兑现承诺的好处和坏处Feb 18, 2024 pm 08:06 PM

在日常生活中,我们常常会遇到承诺与兑现之间的问题。无论是在个人关系中,还是在商业交易中,承诺的兑现都是建立信任的关键。然而,承诺的利与弊也常常会引起争议。本文将探讨承诺的利与弊,并给出一些建议,如何做到言出必行。承诺的利是显而易见的。首先,承诺可以建立信任。当一个人信守承诺时,他会让别人相信自己是一个可信赖的人。信任是人与人之间建立起的纽带,它可以让人们更加

深入了解Promise.resolve()深入了解Promise.resolve()Feb 18, 2024 pm 07:13 PM

Promise.resolve()详解,需要具体代码示例Promise是JavaScript中一种用于处理异步操作的机制。在实际开发中,经常需要处理一些需要按顺序执行的异步任务,而Promise.resolve()方法就是用来返回一个已经Fulfilled状态的Promise对象。Promise.resolve()是Promise类的一个静态方法,它接受一个

实例解析ES6 Promise的原理和使用实例解析ES6 Promise的原理和使用Aug 09, 2022 pm 03:49 PM

利用Promise对象,把普通函数改成返回Promise的形式,解决回调地狱的问题。明白Promise的成功失败调用逻辑,可以灵活的进行调整。理解核心知识,先用起来,慢慢整合吸收知识。

promise对象有哪些promise对象有哪些Nov 01, 2023 am 10:05 AM

promise对象状态有:1、pending:初始状态,既不是成功,也不是失败状态;2、fulfilled:意味着操作成功完成;3、rejected:意味着操作失败。一个Promise对象一旦完成,就会从pending状态变为fulfilled或rejected状态,且不能再改变。Promise对象在JavaScript中被广泛使用,以处理如AJAX请求、定时操作等异步操作。

PHP 函数返回 Promise 对象有什么优势?PHP 函数返回 Promise 对象有什么优势?Apr 19, 2024 pm 05:03 PM

优势:异步和非阻塞,不阻塞主线程;提高代码可读性和可维护性;内置错误处理机制。

一文带你轻松掌握Promise一文带你轻松掌握PromiseFeb 10, 2023 pm 07:49 PM

前端js学习中,让大家最难受的就是异步的问题,解决异步、回调地狱等问题时你必须得学会promise,对于多数前端程序员来说promise简直就是噩梦,本篇文章就是从通俗易懂的角度做为切入点,帮助大家轻松掌握promise

前端开发利器:Promise在解决异步问题中的作用与优势前端开发利器:Promise在解决异步问题中的作用与优势Feb 22, 2024 pm 01:15 PM

前端开发利器:Promise在解决异步问题中的作用与优势引言:在前端开发中,我们经常会遇到异步编程的问题。当我们需要同时执行多个异步操作或处理多个异步回调时,代码往往会变得复杂、难以维护。为了解决这样的问题,Promise应运而生。Promise是一种用于处理异步操作的编程模式,它提供了一种将异步操作以同步方式进行处理的能力,使得代码更加简洁和可读。本文将介

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
3 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser是一個安全的瀏覽器環境,安全地進行線上考試。該軟體將任何電腦變成一個安全的工作站。它控制對任何實用工具的訪問,並防止學生使用未經授權的資源。

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

強大的PHP整合開發環境

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

EditPlus 中文破解版

EditPlus 中文破解版

體積小,語法高亮,不支援程式碼提示功能