Skip to Content

CAP and ASYNC/AWAIT

Basic issue here. I´m having a hard time trying to implement schema.js file. The thing is that when I try to use some async feature such as "await cds.read" or "SELECT.from... " or any async function I cannot manage to make it work properly. The handler ends and every logic after the "await cds.read" runs only after the promise is resolved and the response is already gone ( I told you it was a basic issue ).

So I found this nice blog from our good fellow DJ Adams:

https://blogs.sap.com/2019/08/21/computed-field-example-in-cap/comment-page-1

(I put a comment there)

DJ shows us an example which makes the thing I want to do: implement the after read handler making async calls (await cds.transaction(req).run(SELECT .from(Books) ...) and changing the final response based on the result from this async select. So I implemented it. But strange things are happening. The weird thing is that it sometimes fills the numberOfBooks attribute but most of the times it doesnt. I keep on hitting the refresh button and it keep on changing the results. Here are two responses, one after the other, without reseting or changing anything:

<code>{
@odata.context: "$metadata#Authors",
value: [
{
ID: 101,
name: "Emily Brontë",
numberOfBooks: 1
},
{
ID: 107,
name: "Charlote Brontë",
numberOfBooks: null
},
{
ID: 150,
name: "Edgar Allen Poe",
numberOfBooks: 2
},
{
ID: 170,
name: "Richard Carpenter",
numberOfBooks: null
}
]
}

(hit refresh…)

<code>{
@odata.context: "$metadata#Authors",
value: [
{
ID: 101,
name: "Emily Brontë",
numberOfBooks: null
},
{
ID: 107,
name: "Charlote Brontë",
numberOfBooks: null
},
{
ID: 150,
name: "Edgar Allen Poe",
numberOfBooks: null
},
{
ID: 170,
name: "Richard Carpenter",
numberOfBooks: null
}
]
}

Have you seen it? Edgar Allan Poe who once had 2 books the second time has none. Emily had one and now has none. The others didn´t even showed up the first time. Sometimes I get books for all of them, sometimes for some, but most of the times for none. Straaaange….

I suspect very strongly that it´s the same async/await issue I described above.

I though it was some problem with my installation (VSCode, nodejs, who knows…), so I tried it out on the SAP Business Application Studio, but only to get the same results. This rules out some outdated package os something else.

Has someone else seen things like these?

You can find my code right here:

https://github.com/ecassaro1/ws1/tree/master/p15

Any suggestions?

I´m pretty sure I´m missing something very basic...

Thanks in advance, Eric

Add a comment
10|10000 characters needed characters exceeded

Related questions

1 Answer

  • Best Answer
    Posted on Jul 24, 2020 at 05:22 PM

    Hi Eric,

    you have to wrap your call to the Array.prototype.map() function into a Promise.all() call:

    module.exports = srv => {
    
      const { Books } = srv.entities
    
      srv.after('READ', 'Authors', (authors, req) => {
        return Promise.all(authors.map(async author => {
          const publications = await cds.transaction(req).run(
            SELECT.from(Books).where({ author_ID: author.ID })
          )
          author.numberOfBooks = publications.length
        }));
      });
    }

    See the explanation here: https://flaviocopes.com/javascript-async-await-array-map/

    Kind regards,

    Sebastian

    Add a comment
    10|10000 characters needed characters exceeded

Before answering

You should only submit an answer when you are proposing a solution to the poster's problem. If you want the poster to clarify the question or provide more information, please leave a comment instead, requesting additional details. When answering, please include specifics, such as step-by-step instructions, context for the solution, and links to useful resources. Also, please make sure that you answer complies with our Rules of Engagement.
You must be Logged in to submit an answer.

Up to 10 attachments (including images) can be used with a maximum of 1.0 MB each and 10.5 MB total.