在上一章中,我们看到了如何使用我们的资源并添加了夫妇功能boot
和extend
,这使我们使我们的toJSON
方法成为async
,这就是我们遇到的严重问题,因为JSON.stringify
不支持async
函数,因此我们需要找到一种使它起作用的方法。
异步JSON PARSER
还记得我们的response
课程吗?是的,我们还没有使用它,现在该使用它了,我们将使用它在将数据发送到响应之前使用它来解析数据,但是在更新它之前,我们需要更新我们的request
类以传递处理程序对响应类的输出。
// src/core/http/request.ts
// ...
/**
* Execute the request
*/
public async execute() {
// check for middleware first
const middlewareOutput = await this.executeMiddleware();
if (middlewareOutput !== undefined) {
// 👇🏻 send the response
return this.response.send(middlewareOutput);
}
const handler = this.route.handler;
// 👇🏻 check for validation using validateAll helper function
const validationOutput = await validateAll(
handler.validation,
this,
this.response,
);
if (validationOutput !== undefined) {
// 👇🏻 send the response
return this.response.send(validationOutput);
}
// call executingAction event
this.trigger("executingAction", this.route);
const output = await handler(this, this.response);
// call executedAction event
this.trigger("executedAction", this.route);
// 👇🏻 send the response
await this.response.send(output);
}
因此,我们将把输出传递给响应的send
方法,而不是从中间件,验证或处理程序返回输出,以便我们可以自由处理该输出。
现在让我们更新我们的response
类以处理输出。
// src/core/http/response.ts
// ...
/**
* Send the response
*/
public async send(data?: any, statusCode?: number) {
if (data) {
this.currentBody = data;
}
if (statusCode) {
this.currentStatusCode = statusCode;
}
if (!this.currentStatusCode) {
this.currentStatusCode = 200;
}
// trigger the sending event
this.trigger("sending", this.currentStatusCode, data);
this.baseResponse.status(this.currentStatusCode).send(data);
// trigger the sent event
this.trigger("sent", this.currentStatusCode, data);
// trigger the success event if the status code is 2xx
if (this.currentStatusCode >= 200 && this.currentStatusCode < 300) {
this.trigger("success", data, this.currentStatusCode, this.route);
}
// trigger the successCreate event if the status code is 201
if (this.currentStatusCode === 201) {
this.trigger("successCreate", data, this.currentStatusCode, this.route);
}
// trigger the badRequest event if the status code is 400
if (this.currentStatusCode === 400) {
this.trigger("badRequest", data, this.currentStatusCode, this.route);
}
// trigger the unauthorized event if the status code is 401
if (this.currentStatusCode === 401) {
this.trigger("unauthorized", data, this.currentStatusCode, this.route);
}
// trigger the forbidden event if the status code is 403
if (this.currentStatusCode === 403) {
this.trigger("forbidden", data, this.currentStatusCode, this.route);
}
// trigger the notFound event if the status code is 404
if (this.currentStatusCode === 404) {
this.trigger("notFound", data, this.currentStatusCode, this.route);
}
// trigger the throttled event if the status code is 429
if (this.currentStatusCode === 429) {
this.trigger("throttled", data, this.currentStatusCode, this.route);
}
// trigger the serverError event if the status code is 500
if (this.currentStatusCode === 500) {
this.trigger("serverError", data, this.currentStatusCode, this.route);
}
// trigger the error event if the status code is 4xx or 5xx
if (this.currentStatusCode >= 400) {
this.trigger("error", data, this.currentStatusCode, this.route);
}
return this;
}
这是我们以前的发送方法,我们将在第一次检查之后添加新行。
// src/core/http/response.ts
// ...
/**
* Send the response
*/
public async send(data?: any, statusCode?: number) {
if (data) {
this.currentBody = data;
}
// parse the body and make sure it is transformed to sync data instead of async data
data = await this.parseBody();
// ...
}
我们在此处添加了一个新行,它将解析我们的currentBody
数据,并确保将其转换为同步数据而不是异步数据,因此我们可以将其发送到响应。
身体解析器
现在让我们创建我们的parseBody
方法,但是在我们转到实施之前,让我告诉您此方法的工作流程。
基本上,此方法将调用另一种称为parse
的方法,然后将currentBody
传递到该方法。
我们为什么要这样做?因为我们在这里进行一些递归,因此parse
方法将接收到任何类型的数据并相应地处理,无论其主体或嵌套对象。
现在返回解析方法工作流程
- 如果给定值是
falsy
值,我们将以原样返回。 - 检查传递的数据是否具有
toJSON
方法,如果是的话,则await
并返回结果。 - 检查传递的数据是否为
array
,如果是的话,请循环循环,并在每个项目上调用parse
方法并返回结果。 - 如果它不是普通的对象,也不是一个数组,并且没有
toJSON
,那么我们将只返回它。 - 如果它是一个普通的对象,那么我们将在其键上循环,并在每个值上调用
parse
方法并返回结果。
实际上我们将更改array
的点,我们将检查值是否为iterable
,而不是检查它是否是数组,因为我们要支持任何类型的峰值数据,而不仅仅是数组。
现在让我们去实施。
// src/core/http/response.ts
// we'll need it here to make couple checks later
import Is from "@mongez/supportive-is";
// ...
export class Response {
// ...
/**
* Parse body
*/
protected async parseBody() {
return await this.parse(this.currentBody);
}
// ...
}
现在让我们创建parse
方法。
// src/core/http/response.ts
// ...
export class Response {
// ...
/**
* Parse the given value
*/
protected async parse(value: any): Promise<any> {
// if it is a falsy value, return it
if (!value) return value;
// if it has a `toJSON` method, call it and await the result then return it
if (value.toJSON) {
return await value.toJSON();
}
// if it is iterable, an array or array-like object then parse each item
if (Is.iterable(value)) {
return await Promise.all(
Array.from(value).map((item: any) => {
return this.parse(item);
}),
);
}
// if not plain object, then return it
if (!Is.plainObject(value)) {
return value;
}
// loop over the object and check if the value and call `parse` on it
for (const key in value) {
const subValue = value[key];
value[key] = await this.parse(subValue);
}
return value;
}
}
代码几乎与我上面写的流步骤一样,我们检查了它是否是falsy
值,然后我们将其返回,如果它具有toJSON
方法,则等待它的调用并返回。
如果是iterable
(这就是我们导入的支持是方法),那么我们将循环浏览它,并在每个项目上调用parse
方法并返回结果。
如果不是plainObject
,那么我们将返回它。
如果它是plainObject
,那么我们将循环循环其键,并在每个值上调用parse
方法并返回结果。
关于iterable
数据,您可能会看到代码有些怪异,我们使用Promise.all
等待所有承诺要解决,Promise.all
方法会收到一个数组,这就是为什么我们使用Array.from
转换iToble的数据( arrays( arrays)也被认为是)到一个数组,然后映射每个值以使用parse
方法调用。
现在,如果我们再次尝试返回资源,它将正常工作。
- 结论
在本节中,我们自定义了响应的最终输出,我们使自己的数据解析器将每个async
数据发送为sync
数据。
â•给我买一杯咖啡。
如果您喜欢我的文章并看到对您有用,则可以buy me a coffee,它将帮助我继续前进并继续创建更多内容。
ð项目存储库
您可以在Github
上找到此项目的最新更新ð加入我们的社区
加入我们的社区Discord获得帮助和支持(节点JS 2023频道)。
ð视频课程(阿拉伯语)
如果您想以视频格式学习此课程,则可以在Youtube上找到该课程,该课程是阿拉伯语。
ð奖励内容ð
您可能会看这些文章,这肯定会提高您的知识和生产力。
一般主题
- Event Driven Architecture: A Practical Guide in Javascript
- Best Practices For Case Styles: Camel, Pascal, Snake, and Kebab Case In Node And Javascript
- After 6 years of practicing MongoDB, Here are my thoughts on MongoDB vs MySQL
软件包和库
- Collections: Your ultimate Javascript Arrays Manager
- Supportive Is: an elegant utility to check types of values in JavaScript
- Localization: An agnostic i18n package to manage localization in your project
React JS软件包
课程(文章)