Click here to Skip to main content
15,613,470 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi.
Sorry for not getting the full code first.
This is part of a performance app that processes data from the server into a canvas.

I use async, promise and await to control the flow of functions.
But It doesn't work in the order I want.

CanvasClass is a module object. This is chosen for private data.
In this object, the preparedrawing function checks the data, returns it if there is data, and makes a request to the server if not.

As expected, until the request is sent to the server and the data is received, the task tries to lock in await, but that doesn't work.
Therefore, an error occurs when data that has not yet come from the server is passed.

In the code below, I try to promise and await twice, but it doesn't work.
The code looks complicated
Please focus on the bold font.

I want the following order, ( results of console.log())
'async'
'loadStream'
'f 1'
(6)[{...}, {...}, {...}, {...}, {...}, {...}] <== data from server
'f 2'
'f 3'
'f 4'

But result is
'async'
'loadStream'
'f 1'
'f 2'
'f 3'
'f 4'
(6)[{...}, {...}, {...}, {...}, {...}, {...}] <== data from server

What I have tried:

JavaScript
let abortController = null;
const load_stream = async (data) => {
    if(abortController){ abortController.abort();}
    const url = new URL ("http://192.168.10.21:1080/play");
    if(data){
        Object.entries(data).forEach(entry => {
            const [key, value] = entry;
            url.searchParams.set(key, value);
	});
    }
    abortController = new AbortController();
    try{
        const response = await fetch(url, {signal: abortController.signal });
        if(!response.ok){
            console.error(response.status, response.statusText);
            return [];
        }
        const result = await response.json();
        return result;
    }catch(e){
        console.error(e);
        return [];
    }
};

/* module object */
var canvasClass = function(){
 ......
 // member variables...
 .......
  
return {
      loadStream: async function(_serial_id, _content_id){
             console.log('loadStream');
            const jsonData = { 'pID': _serial_id, 'cID': _content_id };
            const result = await load_stream( jsonData );
            if( imageData.length > 0 ){
                imageData = [];
            }
            imageData = result.responseResultData;
           console.log(imageData);     
           console.log('func');                      
	        this.setPageData();
            return false;
    },
    pageLoading: async (me) => {
            me.loadStream(cont.id, cont.content_id);
            return true;
    },
    prepareDrawing: function( _page ){
            const me = this;
            var i = 0;
            let left_width = '0';
            for( const item of canvasMap ){
		         if(item === undefined)
                       return false;
                do{
                    this.insertCanvasMap({
		            	item: item,
                        page: _page++,
                        num: i++,
                        loading: async (cnt) => {
                            if( pageData[cnt] === undefined ){
                                console.log('async');
                                let res =  await new Promise((resolve, reject) => {
                                    let rt = me.pageLoading(me);
                                    console.log('f 1');
                                    resolve(rt);
                                })
                                return res;
                            }else{
                                return true;
                            }
                        }
                      } );
                }while( i < 2 );
           }
     },
     insertCanvasMap: async ( _args ) => {
            let res = await new Promise((resolve, reject) => {
                let result = _args['loading']( _args['page'] );
                resolve(result);
            });

            if( res !== ''){
                    console.log(res+' f 2');
                   _args['item'].display({
                    image: pageData[_args['page']],
                    subtitle: subtext.page[_args['page']]
            },
            {
                    display: function(_canvas){
                          _canvas.drawImage();
                          console.log('f 3');
                    },
		           getPage: function(_page_num){
		            	page_set[_args['num']] = _page_num;
                        console.log('f 4');
                    }
                })                
	    }
	},
}
}
Posted
Updated 23-Jan-23 1:03am
v2

I think the problem here is that in order for async/await to function correctly, all methods within the chain need to be async. Let's take a look at your methods:

JavaScript
// This is async, so this is fine
loadStream: async function(_serial_id, _content_id){

// This is async but you're not calling await on the loadStream() call
// so this will not block and return immediately
pageLoading: async (me) => {
    me.loadStream(cont.id, cont.content_id);

// This is not async so it can't be awaited
prepareDrawing: function( _page ){

    // This is also not async, so it will return immediately
    // regardless of any child awaits
    this.insertCanvasMap({
        item: item,
        page: _page++,
        num: i++,
        loading: async (cnt) => {

And looking at the nested bit of code in prepareDrawing():
JavaScript
// If you make pageLoading() async then you could just replace this:
let res =  await new Promise((resolve, reject) => {
  let rt = me.pageLoading(me);
  console.log('f 1');
  resolve(rt);
})

// With this:
let res = await me.pageLoading(me);

All being said, you probably need to break this code out into more manageable chunks so you can properly see the flow of how they're supposed to work. It's fine if you want to declare the functions separately and then just inject them into the object, like so:
JavaScript
async function _pageLoading(me) {
  await me.loadStream(cont.id, cont.content_id);
  return true;
}

...

return {
  ...

  pageLoading: _pageLoading,

};

This code is quite difficult to read and follow, especially when you're trying to work out how the async/await code should flow. Break this down into smaller pieces (smaller functions) so then you can really observe how it should be working.
 
Share this answer
 
Comments
Chopin2001 23-Jan-23 5:25am    
thank you. And I'm so sorry. It would be nice if I can explain the code more clearly, but that's hard for me. Because I don't speak English.
Nonetheless, thank you so much for reading and replying.
Chris Copeland 23-Jan-23 5:35am    
No need to apologise 😊 it's just very easy to get carried away when writing code and things can become difficult to follow very quickly! I wasn't criticising your English (no complaints from me there), just wanted to highlight how important it is to keep code simple and easy to follow. If you break the code down into more manageable chunks I imagine you may have a better time working out which parts aren't awaiting correctly!
Chopin2001 23-Jan-23 7:03am    
Thanks Chris. I solve it. :)
Thanks for the advice. A good enough memorable point.
I solved it thanks.
First I deleted the pageloading function and modified it like this:
JavaScript
do{
 ...
 if(pageData[cnt] === undefined ){
     console.log('async');
      let res = await me.loadStream(cont.id, cont.content_id);
      console.log('f 1');
      return res;
   }
   return true;
   ...
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900