为什么des Node JS不执行异步函数?



请考虑这个例子-

p。S -findByIdAndRemove是一个Mongoose函数,用来处理MongoDB。

Block 1:-

try {
Product.findByIdAndRemove(prodId);
console.log("Product Deleted");
} catch (err) {
//...
}

Block 2:-

try {
        await Product.findByIdAndRemove(prodId);
console.log("Product Deleted");
} catch (err) {
//...
}

当试图删除一个产品时,如果我使用Block 1,该产品不会被删除。但是console.log将被执行。

然而,当试图使用Block 2时,产品将被删除,然后执行console.log

现在,我明白Nodejs是异步的,不会等待产品删除完成。这就是执行console.log的原因。在Block 2中,我们强制Node JS等待Async函数,即Delete Request结束,然后再执行下一条语句,即console.log。

但是,假设我不使用Async....Await或Promise或Callback,就像Block 1一样。不管异步执行,Node JS不应该执行查询,即使它移动到下一个语句。我的意思是,很明显Node不会等待产品删除发生。它将执行该命令,并继续执行console.log。但是,它仍然应该在某个时候执行产品删除。然而,即使等待了一段时间后,我发现Node JS根本不执行异步函数,除非它是同步执行的(使用Async await,或promise等)。

所以,我的问题是,为什么Node JS完全停止执行异步函数,而不是在一定时间后完成执行,除非使用Async..await或Promise或callback同步处理。

这是对我的评论的扩展。

当尝试删除产品时,如果我使用Block 1,产品不会被删除。但是console.log将被执行。

然而,当试图使用Block 2时,产品将被删除和然后console.log将被执行。

正如你所知道的,唯一的区别是await被遗漏了。了解await是什么:它只不过是"语法糖",或者换句话说,是使用.then().catch()的一种更美观但技术上等效的方式。这不是魔法。

这对以后很重要。

现在,我明白Nodejs是异步的,不会等待待完成的产品删除。这就是console.log的原因是执行。在Block 2中,我们强制Node JS等待Async函数,即删除请求在执行下一个语句之前结束,即执行console.log。

如果findByIdAndRemove(没有await,then()callback)启动了一些工作并返回了一个Promise,那么这将是true。但是注意如果。这不是这里发生的事情。

然而,假设我不使用Async....Await, Promise, Callback,就像Block 1一样。不管异步执行,不应该Node JS执行查询,即使它移动到下一条语句。

可以,但是库不需要在那个时候执行查询。

我的意思是,很明显Node不会等待Product删除发生。它将执行该命令,并继续执行console.log。但是,它仍然应该在某个时候执行Product delete。

问题的关键是:

delete函数删除一条记录,然后返回一个承诺。

而:

delete函数返回一个具有then()方法的对象。仅当它的then()方法被调用时会发生什么事吗?


为了演示,让我们制作一个非常简单的伪(SQL)查询生成器。

class Query {
constructor(table) {
console.log("Starting a new query (nothing async is happening)");
this.table = table;
}
findById(id) {
console.log("Adding a where filter (nothing async is happening)");
this.whereFilter = `WHERE id = ${id}`;
return this;
}
sort(by, asc = true) {
console.log("Adding a sort option (nothing async is happening)");
this.sortOption = `ORDER BY ${by} ${asc ? 'ASC' : 'DESC'}`;
return this;
}
limit(n) {
console.log("Adding a limit option (nothing async is happening)");
this.limitOption = `LIMIT ${n}`;
return this;
}
toString() {
return `
SELECT *
FROM ${this.table}
${this.whereFilter || ''}
${this.sortOption  || ''}
${this.limitOption || ''}
`.trimEnd();
}
then(cb) {
// The user has called .then() or `await` on this instance.
// Only now execute the database query.
// We'll use a timeout to fake latency.
// This always returns the same fake user.
console.log(`Now executing an async task`);
console.log(`querying the database for: ${this.toString()}`);
return new Promise(resolve =>
setTimeout(resolve, 1000, [{id: 7, name: "Example User"}])
).then(cb);
}
}

现在对一些测试:

const user1 = await new Query("users").findById(1);
console.log("(Result of query 1) Found user", user1);
new Query("users").findById(7).then((user2) => {
console.log("(Result of query 2) Found user", user2);
});
console.log(`Because we don't await this promise, 
it can resolve at any time in the future.`);

这是直观的,并按您的期望工作。

// Until the query is awaited / then() is called, 
// there are no asynchronous processes.
const query = new Query("users");
query.limit(10);
query.findById(77);
query.sort("name");
const user3 = await query;
console.log("(Result of query 3) Found user", user3);

在完成await之前,数据库(或者在本例中,timeout)甚至不会以任何方式被触及。我们建立一个查询。然后再执行。

// await / then() at any time.
const query2 = new Query("users");
query2.limit(10);
const user4 = await query2;
console.log("(Result of query 4) Found user", user4);
// Or even like this.
const query3 = new Query("users").limit(10);
const user5 = await query3.sort("id", false);
console.log("(Result of query 5) Found user", user5);

大同小异

最新更新