2

Its my first work with async/await

i call several api methods and tryne inject data from response body to html-DOM
as you can see i added some async await because i make call to other function with catch
and this works really fine (as i can see from console.log)
but when i trying insert my result to html it returning "undefined"
i have done some tips with return new Promise, but nothing help

async function getProduct(productId) {
    var productTitle = '';
    return fetch('http://193.176.79.173/api/products/' + productId, {
            method: 'GET'
        })
        .then((response) => response.json())
        .then(function(data) {
            return data['data']['title'];
        })
}

async function getProducts(orderId) {
    fetch('http://193.176.79.173/api/orders/20210524155243107', {
            method: 'GET'
        })
        .then((response) => response.json())
        .then(async function(data) {
            var productsText = '';
            console.log(data);
            for (var i = 0; i < data['orderProducts'].length; i++) {
                var product = await getProduct(data['orderProducts'][i].product_id);
                console.log(product);
                productsText += '<div class="mdl-card__title">' +
                    '<h2 class="mdl-card__title-text">' + await getProduct(data['orderProducts'][i].product_id) +
                    '/h2>';
                console.log(productsText);
            }
            return new Promise((resolve, reject) => {
                setTimeout(() => {
                    resolve(productsText);
                }, 1000);
            });

        })
}

var myList = document.querySelector('#list');
async function drawTable() {
    fetch('http://193.176.79.173/api/paidOrders/')
        .then((response) => response.json())
        .then(async function(data) {
            var products = '';
            for (var i = 0; i < data.data.length; i++) {
                var listItem = document.createElement('div');
                var orderId = data.data[i].id;
                orderIdNew = orderId.toString();
                var lastChar = orderIdNew.substr(orderIdNew.length - 1);
                lastChar = parseInt(lastChar, 10) - 1;
                var orderIdNewNew = orderIdNew.replace(/.$/, lastChar);
                listItem.id = orderIdNewNew;
                products = await getProducts(orderIdNewNew);
                listItem.classList.add("mdl-card", "mdl-shadow--2dp", "mdl-cell", "mdl-cell--4-col");
                listItem.innerHTML = '<div style="padding: 16px"> Заказ № ' + orderIdNewNew +
                    '<div class="flex"><b>Статус:</b> ' + data.data[i].status + '</div>' +
                    '<div class="flex"><b>Сумма:</b> ' + data.data[i].summ + '</div>' +
                    '<b>Состав заказа:</b> </div>' +
                    products +
                    '</div>'
                myList.appendChild(listItem);
            }
        })
        .then((data) => {
            console.log(data);
        });
}

setTimeout(function() {
    drawTable()
}, 2000);

But in the end i get undefined instead of "products" value

Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
fourston
  • 25
  • 1
  • 5
  • 2
    Your `getProducts` and `drawTable` functions have no `return` statement. In general, avoid [putting a `.then(…)` chain in an `async` function](https://stackoverflow.com/a/54387912/1048572)! – Bergi May 24 '21 at 22:32
  • 1
    There's no point in marking a function as `async` if you aren't going to use `await` inside it. – Quentin May 24 '21 at 22:33
  • @Bergi, technically putting a .then in an async function is fine. It's _awaiting_ a .then chain that is worth restructuring to be a series of awaits. Here, the promise is neither returned nor awaited -- which is a bug, albeit a common one we all make on our learning journey. – Wyck May 25 '21 at 00:28
  • @Wyck This was generic advice, and I even deliberately rephrased my boilerplate because they weren't using `await` :-) And while it might technically work, I still recommend to avoid `then` calls in `async` functions until you're familiar with the finer details. – Bergi May 25 '21 at 01:18

2 Answers2

4

It seems like a code management problem. Unfortunately, I can't test it to solve it for you, but I've noticed a few issues.

The first one (like @Bergi mentioned) is that the two functions getProducts and drawTable don't return anything

The second issue is that you're not really taking full advantage of async & await, for example, you can write the functiongetProduct like so:

async function getProduct(productId) {
    var productTitle = '';// this is useless btw
    let response = await fetch('http://193.176.79.173/api/products/' + productId, {
        method: 'GET'
    });
    let json = await response.json();
    let result = json['data']['title'];
    return result;
}

This way you can make the code lot easier to read and debug

So try replacing all .then( with async/await syntax, and add return to getProducts and drawTable, then you'll notice the error

And finally, if you're new to async/await I would recommend you those two videos:
16.13: async/await Part 1 - Topics of JavaScript/ES8
16.14: async/await Part 2 - Topics of JavaScript/ES8
They're very similar to your case

First dev
  • 495
  • 4
  • 17
0

agree to the 2 comments above. You have to return something inside a async function, or throw an exception, that lead to .then or .catch.

You can await a fetch.then(...toJSON...) that returns a normal object inside a async function. Or make a long chain calling, put all codes inside .then(...).

see documents at:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises

https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch

sdrkyj
  • 75
  • 1
  • 10