提问人:Carl Sagan 提问时间:4/25/2023 更新时间:9/5/2023 访问量:53
将 mongoose findbyid 与 express 一起使用从数据库中获取对象仅适用于回调?回调在较新的 js 框架中的重要性?
Using mongoose findbyid with express to get object from database only works with callback? Callbacks importance in newer js frameworks?
问:
我正在做关于 MDN 文档的快速本地库教程,并想尝试在不使用回调方法的情况下返回对象。
当将 id 的请求对象参数传递给 findById mongoose 方法并记录到控制台时,这是 bookinstance 的内容:var bookinstance = BookInstance.findById(req.params.id);
BookInstance.findOne({ _id: '63e17d2395d1d4e11604cf22' })
将 id 和回调函数传递给 findById 方法时,如下所示
BookInstance.findById(req.params.id, function(err, instance) {
if (err) {
next(err);
}
console.log('findById callback: ' + instance);
res.render("bookinstance_delete", {
title: "Book Instance Delete",
id: instance._id,
imprint: instance.imprint,
book: instance.book
})
})
并记录到控制台,则输出预期的 Book 实例对象:
findById callback: {
_id: new ObjectId("63e17d2395d1d4e11604cf22"),
book: new ObjectId("63e17d2395d1d4e11604cf16"),
imprint: 'New York Tom Doherty Associates, 2016.',
status: 'Available',
due_back: 2023-02-06T22:20:19.928Z,
__v: 0
}
这与一般的 javascript 有关吗?这是我第一次接触 express、node、mongoose 以及所有这些基于 javascript 的框架和技术,它们似乎都大量使用回调。回调的目的只是为了有一种方式说,嘿,执行这个任务,当你完成后,做这个任务吗?
当我不使用回调时,返回的对象是对象和方法(findone),执行时会给我 bookinstance 对象和属性。那么回调函数会把那个对象作为实例参数,执行它并返回这个对象吗?这是怎么回事?
答:
回调是 JavaScript 语言的重要组成部分。在传统的同步编程中,每一行代码都被认为是一系列连续的步骤。每个人都阻止下一个,直到他们完成任务。从概念上讲,这很容易编写、遵循和调试。
但是,在异步编程中,任务不需要等待每行代码完成,然后才能开始另一行代码。例如,为什么程序必须等待数据库查询完成,以便可以从文件中读取或上传图像。这些耗时的任务可以同时完成吗?在同步编程中,完成这些任务所需的时间相加,但在异步编程中,您可以同时执行这些任务,因此您应该这样做。
但随之而来的问题是,要知道每个异步任务何时完成。在同步编程中,您的代码将移动到下一行代码。在 JavaScript/Node.js 异步编程中,有一个回调,它 从本质上讲,只是另一个函数,它以 异步操作。
你似乎已经掌握了这个概念:
所以回调的目的只是为了有一种方式说,嘿,执行这个任务,当你完成时,做这个任务?
回调模式只是 JavaScript 中的几种设计模式之一,可以处理异步任务,但它们有其缺点 - 回调地狱。
在现代 Node.js 中,我们有更新的设计模式,可以使用 Promise 和 async/await 处理控制流。它们具有更好的语法,并且更易于阅读、编写和调试。由于 Node.js 是单线程的,因此这些较新的设计模式使运行不会阻塞单线程的响应式 Web 应用程序变得更加简单。
上面使用回调模式的示例:
BookInstance.findById(req.params.id, function(err, instance) {...});
是一种非常过时的方法,这些天你会发现的所有文档都概述了 OR 模式。Promises
async/await
顺便说一句,猫鼬 findById 方法触发了 findOne 方法,这就是您看到 .BookInstance.findOne({ _id: '63e17d2395d1d4e11604cf22' })
虽然 mongoose 查询不是 Promise,但您仍然可以将 Promise 实现与 和 块一起使用:then
catch
BookInstance.findById(req.params.id).then((doc) => {
console.log('Found Instance: ', doc);
})
.catch((err) => {
console.log(err);
});
这是与模式一起的:async/await
app.get('/books/:id', async (req, res) => { // < Note the use of async keyword
try {
const result = await BookInstance.findById(req.params.id); // < Note the use of await keyword
console.log(result);
} catch(err) {
console.log(err);
}
});
一般来说,mongoose 和 Node.js 的一个问题是,如果你在进行数据库查询时不使用 or 模式,你会遇到意想不到的结果。例如,你写道:Promises
async/await
当我没有使用回调时,返回的对象是对象和方法(findone),
这可能适用于一个小查询,但如果集合中有数千个或数百万个文档,并且对它们执行了查询,则脚本实际上可能会在查询完成之前结束,并且不会返回任何文档。运行查询可能需要 200 毫秒,但脚本从开始到结束仅花费 150 毫秒。如果没有回调、Promise 或 async/await,你的代码只会移动到最后,你不会从数据库中得到结果。
评论