Javascript 在继续使用函数更改DOM之前,如何等待异步数据库调用的解析?
我试图动态地向表中添加元素,有点像分类账。我有几个HTML按钮。按钮从MongoDB集合动态加载到DOM。我使用NodeJS,使用PUG/Jade作为视图引擎,并将DB中的_id值作为每个按钮的id值。通过这种方式,我可以使用onclick函数查询数据库中的其他属性 每次单击按钮时,我都会对后端运行一个获取调用,以获取存储在MongoDB中的price属性:Javascript 在继续使用函数更改DOM之前,如何等待异步数据库调用的解析?,javascript,node.js,mongodb,asynchronous,synchronous,Javascript,Node.js,Mongodb,Asynchronous,Synchronous,我试图动态地向表中添加元素,有点像分类账。我有几个HTML按钮。按钮从MongoDB集合动态加载到DOM。我使用NodeJS,使用PUG/Jade作为视图引擎,并将DB中的_id值作为每个按钮的id值。通过这种方式,我可以使用onclick函数查询数据库中的其他属性 每次单击按钮时,我都会对后端运行一个获取调用,以获取存储在MongoDB中的price属性: function getPriceFromDatabase() { var target = event.target; var id =
function getPriceFromDatabase() {
var target = event.target;
var id = target.id;
var url = '/menus/' + id;
fetch(url, {
method: 'GET'
}).then(function(res){
if(!res.ok) console.log("Error");
else return res.json().then(function(result){
var returnedItem = JSON.parse(result)
console.log("Item Price: " + returnedItem[0].itemPrice);
return returnedItem[0].itemPrice;
}).catch(function(err){
console.log(err);
});
});
}
这个很好用
我的问题是,当我试图调用此函数向表中添加新行时
function createTableElement () {
var newTableRow = document.createElement("tr");
var target = event.target;
var nameCell = document.createElement("td");
var nameText = document.createTextNode(target.textContent);
nameCell.appendChild(nameText);
newTableRow.appendChild(nameCell);
var priceOfItem = getPriceFromDatabase()
var priceCell = document.createElement("td");
var priceText = document.createTextNode(priceOfItem);
priceCell.appendChild(priceText);
newTableRow.appendChild(priceCell);
ledgerTable.appendChild(newTableRow);
}
函数运行时不等待getPriceFromDatabase()的结果
这意味着我得到了一个表,其中第一列正确地说明了单击的按钮的名称,但价格列未定义。查询数据库并返回一个值只需要一段时间,到它发生时,调用查询的函数已经完成
我有什么选择?我还是使用承诺和异步函数的新手。我知道fetch返回一个承诺作为响应对象,这就是为什么我可以使用
我已尝试将DOM表函数更改为:
getPriceFromDatabase().then( [construct the rest of the table elements] )
这是无效的,因为.then()不是该函数的属性,因为它不返回承诺。我能做什么
我已经试过了
异步getPriceFromDatabase(){},但它仍然给我一个无法使用的错误
我怎样才能解决这个问题?我必须使用新的Promise()吗?如果有人能给我指出正确的方向,我将不胜感激 getPriceFromDatabase()
是一个异步函数。您需要从中返回承诺,并对返回的承诺使用。然后()
:
function getPriceFromDatabase() {
var target = event.target;
var id = target.id;
var url = '/menus/' + id;
return fetch(url, {
method: 'GET'
}).then(function(res){
if(!res.ok) console.log("Error");
else return res.json().then(function(result){
var returnedItem = JSON.parse(result)
console.log("Item Price: " + returnedItem[0].itemPrice);
return returnedItem[0].itemPrice;
}).catch(function(err){
console.log(err);
throw err;
});
});
}
function createTableElement () {
var newTableRow = document.createElement("tr");
var target = event.target;
var nameCell = document.createElement("td");
var nameText = document.createTextNode(target.textContent);
nameCell.appendChild(nameText);
newTableRow.appendChild(nameCell);
getPriceFromDatabase().then(function(priceOfItem) {
var priceCell = document.createElement("td");
var priceText = document.createTextNode(priceOfItem);
priceCell.appendChild(priceText);
newTableRow.appendChild(priceCell);
ledgerTable.appendChild(newTableRow);
});
}
更改摘要:
fetch(url)
更改为return fetch(url)
,从而返回承诺var priceOfItem=getPriceFromDatabase()
更改为getPriceFromDatabase。然后(…)
事件
传递到这两个函数中,而不是依赖全局函数
我尝试将DOM表函数更改为:
getPriceFromDatabase()。然后([构造其余的表元素])
这对您不起作用,因为您没有从getPriceFromDatabase()
返回承诺,因此返回值上没有.then()
处理程序
我尝试了异步getPriceFromDatabase(){}
,但它仍然给了我一个无法使用的错误
同样的问题。你仍然必须兑现承诺。回答得非常有帮助。你能详细解释一下你对globals的意思吗?我认为这些变量是局部变量,在onClick函数运行后会消失。您的意思是我应该简单地使用“return fetch(event.target.id)”,而不是在fetch调用之前声明它们吗?还是我错过了你想告诉我的?而且,我也不知道我会那样回来。那么,fetch本身就是一个承诺,并且包含一个承诺,其中包含一个响应对象?或者return fetch(…)是返回响应对象本身的一种方法吗?@Mikhail-
fetch()
返回一个承诺。因此,当您执行return fetch()
时,您将从主机函数返回一个承诺。关于事件
我的意思是,您没有将其传递到任何函数中,因此您显然在使用全局事件
对象。在异步函数中,这不是一件好事,因为全局事件在使用它之前可能会发生更改。您应该将事件传递到createTableElement(event)
中,然后再次将其传递到getPriceFromDatabase(event)
。实际上,getPriceFromDatabase()
如果您传入id
则通常更有用。我没有考虑到事件的变化,因为此时我的大多数呼叫都相对较快。我遵照您的建议,将onClick函数更改为createTableElement(this.id)
。通过函数链传递它基本上消除了使用事件对象的需要。再次感谢你的提示。