主頁 > 軟體工程 > 什么在打字稿中回傳這個函式?

什么在打字稿中回傳這個函式?

2022-02-16 16:38:41 軟體工程

當我將滑鼠懸停在關鍵字“功能”上時,描述會顯示:

"(本地函式)(this: any, next: (err?: mongoose.CallbackError | undefined) => void): Promise<void>"

那么它回傳 aPromise<void>還是 simple <void>我什至無法理解這個函式回傳什么?老實說,我不太了解Promise<void>...的概念

userSchema.pre('save', async function (next) {

    let user = this as UserDocument;
    if(!user.isModified('password')){
        return next();
    }

    const salt = await bcrypt.genSalt(config.get<number>('saltWorkFactor'));
    const hash = await bcrypt.hash(user.password, salt);

    user.password = hash;
    return next();

})

uj5u.com熱心網友回復:

這個問題真的很有趣。您的函式回傳 a ,它與預期的回傳型別Promise<void>兼容,但 Mongoose 非常聰明,足以知道如何處理您的 Promise,因此您甚至根本不需要呼叫voidprenext


首先是一些背景:

  • void在 TypeScript 中具有特殊含義,表示回傳值可以是任何值;該值經常出現undefined(因為這是一個函式在沒有return陳述句的情況下回傳的值),但它不一定是。正如在 TypeScript FAQ中一樣,這使得通過指示回傳值未使用來接受或傳遞回傳值的函式變得很方便。如果您需要提供一個回傳型別為 的函式void,您可以傳回一個回傳 a stringPromise<void>Promise<SomeObject>nullundefined或其他任何內容的函式。
  • 所有async函式都回傳 Promises,這也不例外。APromise<number>是一個 Promise,表示它的then函式將收到一個number; a是一個 Promise,它不會告訴你它的函式接收Promise<void>到什么。thenthen函式仍將被呼叫,除非它有一個錯誤catch你只是不太了解它的論點。
  • 在 Mongoose 的型別中,pre接受一個PreSaveMiddlewareFunction<T>函式,即您撰寫的函式的型別。它接受一個名為next并回傳的函式void:Mongoose聲稱不關心您回傳的內容。你的中間件函式可以是異步的;完成后,您應該呼叫next(帶有錯誤物件,如果有的話),并且該呼叫next也回傳void.

您傳遞給pre回傳型別Promise<void>的函式:該函式async絕對回傳一個承諾,并且您的return next();意思是承諾決議為任何next回傳,定義為void. 你不知道next回傳什么,也不應該關心它。你甚至不需要return next(),你只需要呼叫它:它只是一個回呼,所以你可以告訴 Mongoose 你的中間件已經完成并報告任何錯誤。

所以你的 return ,但這適用于:的定義,不關心你的函式有什么樣的回傳值 ( async function)只要你打電話來表明你已經完成了。Promise<void>preprevoidnext


可是等等!報告您的異步函式已完成以及是否有錯誤正是Promises 旨在解決的問題,而next回呼模式正是 Promises 旨在取代的那種模式。next如果你要回傳一個 Promise,當 Mongoose 可以看到你回傳的 Promise 時,你為什么還要打電話呢?

事實上,在 Mongoose 5.x 或更高版本中,這正是發生的情況如果您傳入的函式pre回傳一個 Promise,那么您可以使用它而不是呼叫next. next為了兼容性,您仍然可以手動呼叫,但在您的情況下,您可以洗掉return next()并且一切都會繼續作業。請參閱中間件檔案:

mongoose 5.xnext()中,您可以使用回傳承諾的函式,而不是手動呼叫。特別是,您可以使用async/await.

schema.pre('save', function() {
  return doStuff().
    then(() => doMoreStuff());
});

// Or, in Node.js >= 7.6.0:
schema.pre('save', async function() {
  await doStuff();
  await doMoreStuff();
});

檔案進一步解釋了為什么return next()是一種模式:

如果使用next(),則next()呼叫不會停止中間件函式中的其余代碼執行。使用earlyreturn模式可以防止在呼叫next().

const schema = new Schema(..);
schema.pre('save', function(next) {
  if (foo()) {
    console.log('calling next!');
    // `return next();` will make sure the rest of this function doesn't run
    /*return*/ next();
  }
  // Unless you comment out the `return` above, 'after next' will print
  console.log('after next');
});

總而言之,預期的回傳型別void與您回傳 a 的事實兼容Promise<void>,但它隱藏了這樣一個事實,即最近版本的 Mongoose 足夠聰明,可以檢查您是否回傳 Promise 并在不需要 a 的情況下做正確的事情打電話給next. 它們是兩種不同的風格,兩者都有效。

uj5u.com熱心網友回復:

長答案短:它回傳一個Promise<void>


回呼

要了解原因,這里有一些細節。首先必須了解 node.js 中的回呼。回呼是 node.js 作業方式的基本結構/功能之一。

你可以說 node.js 基本上是一個事件驅動的編程“框架”(大多數人會對框架這個詞皺眉......)。這意味著您告訴節點,如果發生某件事,它應該執行某個操作/功能(回呼)。

為了讓 node 理解我們,我們通常將回呼函式作為引數提供給另一個函式,該函式將完成“監聽事件”的作業并執行我們給它的回呼。所以執行回呼的不是“我們”,而是事件監聽器。

在你的情況下,

userSchema.pre('save', async function (next) {

pre是函式(Mongoose 的 userSchema 中的一種方法),save是必須回應的事件,async function (next) {是回呼或事件之后必須執行的操作。

您會注意到您的回呼正在回傳next(),但是next()回傳void,這意味著您的回呼正在回傳void那它為什么又回來了Promise<void>

事實是,在您的情況下,您的回呼是一個異步函式。每個異步函式都會回傳一個 Promise。它是一個異步函式,因為它正在等待它內部的另一個承諾(甚至兩個承諾)。它們之所以被隱藏是因為await

const salt = await bcrypt.genSalt(config.get<number>('saltWorkFactor'));
const hash = await bcrypt.hash(user.password, salt);

注意:這些bcrypt方法在 CPU 和時間方面非常昂貴(這也是一項安全功能)。

這也意味著通常在您的代碼中

const hash = await bcrypt.hash(user.password, salt);
user.password = hash;

您無法“立即”獲得 the 的hash價值user.password,更糟糕的是,您甚至不知道它何時會到來。您的程式會停止并等到bcrypt完成其業務嗎?如果你有很多async功能,你的程式將是奧運會最慢冠軍的最愛。

這些承諾是怎么回事,我們怎么能不被貼上老年專案的標簽?


承諾

這是一個快速/長評論,試圖解釋承諾的概念。

在“正常”代碼中,每一行代碼都會在下一行代碼之前執行并“完成”。例如:(帶烹飪)

  • 將黃油和糖混合,
  • 一次加一個雞蛋,等等。

或在您的代碼中:

 let user = this as UserDocument;
if(!user.isModified('password')){
    return next();
}

承諾是在下一行代碼之前執行但未完成的特定代碼。前任:

  • 當蛋糕在烤箱里時(承諾),
  • you prepare the frosting,
  • but you can't put it until the cake in baked (the "then" action of promises).

Note: Your code is using await so there is no "explicit" then method.

You will have many example of "promises" things in everyday life. you may have heard of asynchronous code = not one after the other, not in sync, ...

  • Turning on an alarm to wake you in the morning, then you make the promise that you will not ignore it;
  • putting a reminder on the calendar then you make the promise that you will go to that job interview; etc.

All the while, you continue with your life after making those promises.

In code, a function that returns a promise will have a then method where you tell the computer what to do when when the "alarms goes off". It is usually written like this

mypromise().then(doThisThingFunction)

const continueWithMyLife = true

In this way the then method is very similar to the callback of node.js. It is just expressed in a different way in the code and is not specific to node (callbacks are also not specific to node...). One very important difference between them is that callbacks are something that the listener "do" and promises is something that resolves (hopefully) to a returning value.


Async/Await

Nowadays it is common to use async/await. Fortunately/unfortunately it basically hides the asynchronous behaviour. Better flow of reading the code, but also much worse understanding of promises for new programmers.

After a await, there is no then method (Or you could say that the following line of code is the then action). There is no "continuing with your life". There is only "waiting until the alarms goes off", So the next line after the await is essentially the "get out of the bed action".

That is why, in your code, the hash value is available in the next line. Basically in the "old way" to write promises

user.password = hash;

would be inside the then function.

And that is also why it is returning Promise<void>


But still, all these analogies won't really help. The best is to try it in everyday code. There is nothing like experience to understand anything.

轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/424008.html

標籤:节点.js 打字稿 猫鼬 承诺 返回型

上一篇:MongoError:無法識別的運算式'$last'(“版本”:“5.0.4”)

下一篇:有誰知道這個錯誤的修復方法(TypeError:無法分配給物件'#<QueryCursor>'的只讀屬性'map')

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • Git本地庫既關聯GitHub又關聯Gitee

    創建代碼倉庫 使用gitee舉例(github和gitee差不多) 1.在gitee右上角點擊+,選擇新建倉庫 ? 2.選擇填寫倉庫資訊,然后進行創建 ? 3.服務端已經準備好了,本地開始作準備 (1)Git 全域設定 git config --global user.name "成鈺" git c ......

    uj5u.com 2020-09-10 05:04:14 more
  • CODING DevOps 代碼質量實戰系列第二課,相約周三

    隨著 ToB(企業服務)的興起和 ToC(消費互聯網)產品進入成熟期,線上故障帶來的損失越來越大,代碼質量越來越重要,而「質量內建」正是 DevOps 核心理念之一。**《DevOps 代碼質量實戰(PHP 版)》**為 CODING DevOps 代碼質量實戰系列的第二課,同時也是本系列的 PHP ......

    uj5u.com 2020-09-10 05:07:43 more
  • 推薦Scrum書籍

    推薦Scrum書籍 直接上干貨,推薦書籍清單如下(推薦有順序的哦) Scrum指南 Scrum精髓 Scrum敏捷軟體開發 Scrum捷徑 硝煙中的Scrum和XP : 我們如何實施Scrum 敏捷軟體開發:Scrum實戰指南 Scrum要素 大規模Scrum:大規模敏捷組織的設計 用戶故事地圖 用 ......

    uj5u.com 2020-09-10 05:07:45 more
  • CODING DevOps 代碼質量實戰系列最后一課,周四發車

    隨著 ToB(企業服務)的興起和 ToC(消費互聯網)產品進入成熟期,線上故障帶來的損失越來越大,代碼質量越來越重要,而「質量內建」正是 DevOps 核心理念之一。 **《DevOps 代碼質量實戰(Java 版)》**為 CODING DevOps 代碼質量實戰系列的最后一課,同時也是本系列的 ......

    uj5u.com 2020-09-10 05:07:52 more
  • 敏捷軟體工程實踐書籍

    Scrum轉型想要做好,第一步先了解并真正落實Scrum,那么我推薦的Scrum書籍是要看懂并實踐的。第二步是團隊的工程實踐要做扎實。 下面推薦工程實踐書單: 重構:改善既有代碼的設計 決議極限編程 : 擁抱變化 代碼整潔代碼 程式員的職業素養 修改代碼的藝術 撰寫可讀代碼的藝術 測驗驅動開發 : ......

    uj5u.com 2020-09-10 05:07:55 more
  • Jenkins+svn+nginx實作windows環境自動部署vue前端專案

    前面文章介紹了Jenkins+svn+tomcat實作自動化部署,現在終于有空抽時間出來寫下Jenkins+svn+nginx實作自動部署vue前端專案。 jenkins的安裝和配置已經在前面文章進行介紹,下面介紹實作vue前端專案需要進行的哪些額外的步驟。 注意:在安裝jenkins和nginx的 ......

    uj5u.com 2020-09-10 05:08:49 more
  • CODING DevOps 微服務專案實戰系列第一課,明天等你

    CODING DevOps 微服務專案實戰系列第一課**《DevOps 微服務專案實戰:DevOps 初體驗》**將由 CODING DevOps 開發工程師 王寬老師 向大家介紹 DevOps 的基本理念,并探討為什么現代開發活動需要 DevOps,同時將以 eShopOnContainers 項 ......

    uj5u.com 2020-09-10 05:09:14 more
  • CODING DevOps 微服務專案實戰系列第二課來啦!

    近年來,工程專案的結構越來越復雜,需要接入合適的持續集成流水線形式,才能滿足更多變的需求,那么如何優雅地使用 CI 能力提升生產效率呢?CODING DevOps 微服務專案實戰系列第二課 《DevOps 微服務專案實戰:CI 進階用法》 將由 CODING DevOps 全堆疊工程師 何晨哲老師 向 ......

    uj5u.com 2020-09-10 05:09:33 more
  • CODING DevOps 微服務專案實戰系列最后一課,周四開講!

    隨著軟體工程越來越復雜化,如何在 Kubernetes 集群進行灰度發布成為了生產部署的”必修課“,而如何實作安全可控、自動化的灰度發布也成為了持續部署重點關注的問題。CODING DevOps 微服務專案實戰系列最后一課:**《DevOps 微服務專案實戰:基于 Nginx-ingress 的自動 ......

    uj5u.com 2020-09-10 05:10:00 more
  • CODING 儀表盤功能正式推出,實作作業資料可視化!

    CODING 儀表盤功能現已正式推出!該功能旨在用一張張統計卡片的形式,統計并展示使用 CODING 中所產生的資料。這意味著無需額外的設定,就可以收集歸納寶貴的作業資料并予之量化分析。這些海量的資料皆會以圖表或串列的方式躍然紙上,方便團隊成員隨時查看各專案的進度、狀態和指標,云端協作迎來真正意義上 ......

    uj5u.com 2020-09-10 05:11:01 more
最新发布
  • windows系統git使用ssh方式和gitee/github進行同步

    使用git來clone專案有兩種方式:HTTPS和SSH:
    HTTPS:不管是誰,拿到url隨便clone,但是在push的時候需要驗證用戶名和密碼;
    SSH:clone的專案你必須是擁有者或者管理員,而且需要在clone前添加SSH Key。SSH 在push的時候,是不需要輸入用戶名的,如果配置... ......

    uj5u.com 2023-04-19 08:41:12 more
  • windows系統git使用ssh方式和gitee/github進行同步

    使用git來clone專案有兩種方式:HTTPS和SSH:
    HTTPS:不管是誰,拿到url隨便clone,但是在push的時候需要驗證用戶名和密碼;
    SSH:clone的專案你必須是擁有者或者管理員,而且需要在clone前添加SSH Key。SSH 在push的時候,是不需要輸入用戶名的,如果配置... ......

    uj5u.com 2023-04-19 08:35:34 more
  • 2023年農牧行業6大CRM系統、5大場景盤點

    在物聯網、大資料、云計算、人工智能、自動化技術等現代資訊技術蓬勃發展與逐步成熟的背景下,數字化正成為農牧行業供給側結構性變革與高質量發展的核心驅動因素。因此,改造和提升傳統農牧業、開拓創新現代智慧農牧業,加快推進農牧業的現代化、資訊化、數字化建設已成為農牧業發展的重要方向。 當下,企業數字化轉型已經 ......

    uj5u.com 2023-04-18 08:05:44 more
  • 2023年農牧行業6大CRM系統、5大場景盤點

    在物聯網、大資料、云計算、人工智能、自動化技術等現代資訊技術蓬勃發展與逐步成熟的背景下,數字化正成為農牧行業供給側結構性變革與高質量發展的核心驅動因素。因此,改造和提升傳統農牧業、開拓創新現代智慧農牧業,加快推進農牧業的現代化、資訊化、數字化建設已成為農牧業發展的重要方向。 當下,企業數字化轉型已經 ......

    uj5u.com 2023-04-18 08:00:18 more
  • 計算機組成原理—存盤器

    計算機組成原理—硬體結構 二、存盤器 1.概述 存盤器是計算機系統中的記憶設備,用來存放程式和資料 1.1存盤器的層次結構 快取-主存層次主要解決CPU和主存速度不匹配的問題,速度接近快取 主存-輔存層次主要解決存盤系統的容量問題,容量接近與價位接近于主存 2.主存盤器 2.1概述 主存與CPU的聯 ......

    uj5u.com 2023-04-17 08:20:31 more
  • 談一談我對協同開發的一些認識

    如今各互聯網公司普通都使用敏捷開發,采用小步快跑的形式來進行專案開發。如果是小專案或者小需求,那一個開發可能就搞定了。但對于電商等復雜的系統,其功能多,結構復雜,一個人肯定是搞不定的,所以都是很多人來共同開發維護。以我曾經待過的商城團隊為例,光是后端開發就有七十多人。 為了更好地開發這類大型系統,往 ......

    uj5u.com 2023-04-17 08:18:55 more
  • 專案管理PRINCE2核心知識點整理

    PRINCE2,即 PRoject IN Controlled Environment(受控環境中的專案)是一種結構化的專案管理方法論,由英國政府內閣商務部(OGC)推出,是英國專案管理標準。
    PRINCE2 作為一種開放的方法論,是一套結構化的專案管理流程,描述了如何以一種邏輯性的、有組織的方法,... ......

    uj5u.com 2023-04-17 08:18:51 more
  • 談一談我對協同開發的一些認識

    如今各互聯網公司普通都使用敏捷開發,采用小步快跑的形式來進行專案開發。如果是小專案或者小需求,那一個開發可能就搞定了。但對于電商等復雜的系統,其功能多,結構復雜,一個人肯定是搞不定的,所以都是很多人來共同開發維護。以我曾經待過的商城團隊為例,光是后端開發就有七十多人。 為了更好地開發這類大型系統,往 ......

    uj5u.com 2023-04-17 08:18:00 more
  • 專案管理PRINCE2核心知識點整理

    PRINCE2,即 PRoject IN Controlled Environment(受控環境中的專案)是一種結構化的專案管理方法論,由英國政府內閣商務部(OGC)推出,是英國專案管理標準。
    PRINCE2 作為一種開放的方法論,是一套結構化的專案管理流程,描述了如何以一種邏輯性的、有組織的方法,... ......

    uj5u.com 2023-04-17 08:17:55 more
  • 計算機組成原理—存盤器

    計算機組成原理—硬體結構 二、存盤器 1.概述 存盤器是計算機系統中的記憶設備,用來存放程式和資料 1.1存盤器的層次結構 快取-主存層次主要解決CPU和主存速度不匹配的問題,速度接近快取 主存-輔存層次主要解決存盤系統的容量問題,容量接近與價位接近于主存 2.主存盤器 2.1概述 主存與CPU的聯 ......

    uj5u.com 2023-04-17 08:12:06 more