如何在继续执行更改 DOM 的函数之前等待异步数据库调用解决?

How to await for async database call to resolve before proceeding with function to alter the DOM?

我正在尝试将元素动态添加到 Table,有点像分类帐。我有几个 HTML 按钮。这些按钮从 MongoDB 集合动态加载到 DOM。我正在使用 NodeJS,使用 PUG/Jade 作为视图引擎,并将数据库中的 _id 值作为每个按钮的 id 值。这样我就可以使用 onclick 函数在数据库中查询其他属性。

每次单击按钮时,我都会 运行 对我的后端进行提取调用,获取存储在 MongoDB:

中的价格 属性
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);
    });
});
}

这很好用。

我的问题是当我尝试调用此函数将新行添加到 table。

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);
}

函数 运行s 无需等待 getPriceFromDatabase()

的结果

这意味着我得到一个 table,其中第一列正确说明了被单击按钮的名称,但价格列未定义。查询数据库和 return 一个值只需要一些时间,当它发生时调用查询的函数已经完成。

我有哪些选择?我仍然是使用 promises 和异步函数的新手。我知道 fetch return 是一个作为响应对象的承诺,这就是为什么我可以使用 .then()

我已经尝试将我的 DOM-table 函数更改为:

getPriceFromDatabase().then( [construct the rest of the table elements] ) 

这是无效的,因为 .then() 不是该函数的 属性,因为它不是 return 承诺。我能做什么?

我试过

async getPriceFromDatabase() {},但它仍然给我一个错误,我不能使用 .then()

我该如何解决这个问题?我必须使用 new Promise () 吗?如果有人能指出我正确的方向,我将不胜感激。

getPriceFromDatabase() 是一个异步函数。您需要 return 它的承诺并在 returned 承诺上使用 .then()

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);
    });
}

更改摘要:

  1. fetch(url) 已更改为 return fetch(url),因此 return 实现了承诺。
  2. var priceOfItem = getPriceFromDatabase() 改为 getPriceFromDatabase.then(...).

此外,您确实应该将 event 传递给两个函数而不是依赖全局函数。


I have tried changing my DOM-table function to something like: getPriceFromDatabase().then( [construct the rest of the table elements] ).

这对你不起作用,因为你没有 return 来自 getPriceFromDatabase() 的承诺,因此 return 值没有 .then() 处理程序。

I tried async getPriceFromDatabase() {}, but it still gives me an error that I can't use .then()

同样的问题。你还是要return兑现承诺。