1

I have an object that looks like this and stores some attributes:

Object description

Basically what I need is to loop through this object and get the file attribute of every key that I would later use in my code to generate multiple Video-React components. I tried to use map() function but the site will crash with the error:

Parsing error: Can not use keyword 'await' outside an async function.

Even though the code sample that I am working with is inside an async function.

Here is my code:

            const response = await dataProvider(GET_MANY, 'vid', { ids: videoId })
            const file = response.data;
            file.map( source => {
                var videoPosition = 0;
                var sigkey = "sigkey";
                var formBody = new FormData();
                formBody.set('ver', "1.2");
                formBody.set('key', "key");
                formBody.set('video_id', file[videoPosition].file);
                formBody.set('user_id', "1234");
                formBody.set('format', "json");
                formBody.set('ip', "");
                formBody.set('tts', "0");
                formBody.set('nonce', Math.round((new Date()).getTime() / 1000));

                var sign_fields = [formBody.get('video_id'), formBody.get('user_id'), formBody.get('ip'), formBody.get('tts'), formBody.get('ver'), formBody.get('key'), formBody.get('nonce')];
                var data = sign_fields.join(':');
                var signature = hmacsha256(data, sigkey);

                formBody.set('sig', signature);

                var formBodyStringified = new URLSearchParams(formBody).toString();

                const resJson = await fetch(Config.api.livebox, {
                    method: 'POST',
                    body: formBodyStringified,
                    headers: {
                        'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
                    }
                }).then(res => res.json());
                const finalJsonUrl = 'https:' + resJson.hls;
                this.setState({ videoSource: finalJsonUrl });
                videoPosition++;
            });

Any suggestions how can I loop through the object?

Thank you in advance.

9
  • use for of instead of map. Also your not using the return of map, so forEach would have been more logical. Commented Oct 15, 2019 at 12:26
  • Put all the code inside a function with a keyword async. and inside that async function you can use as much await Commented Oct 15, 2019 at 12:26
  • Your await fetch does not occur in an async function. Commented Oct 15, 2019 at 12:27
  • You need to include the async keyword in front of the callback passed to response.map, May I also suggest you put the map inside of a Promise.all Commented Oct 15, 2019 at 12:29
  • @Keith Would you mind to post an example please? I am really not good with loops. Commented Oct 15, 2019 at 12:36

2 Answers 2

2

You should include an async tag even inside your map function:

file.map(async source => {
                var videoPosition = 0;
                var sigkey = "sigkey";
                var formBody = new FormData();
                formBody.set('ver', "1.2");
                formBody.set('key', "key");
                formBody.set('video_id', file[videoPosition].file);
                formBody.set('user_id', "1234");
                formBody.set('format', "json");
                formBody.set('ip', "");
                formBody.set('tts', "0");
                formBody.set('nonce', Math.round((new Date()).getTime() / 1000));

                var sign_fields = [formBody.get('video_id'), formBody.get('user_id'), formBody.get('ip'), formBody.get('tts'), formBody.get('ver'), formBody.get('key'), formBody.get('nonce')];
                var data = sign_fields.join(':');
                var signature = hmacsha256(data, sigkey);

                formBody.set('sig', signature);

                var formBodyStringified = new URLSearchParams(formBody).toString();

                const resJson = await fetch(Config.api.livebox, {
                    method: 'POST',
                    body: formBodyStringified,
                    headers: {
                        'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
                    }
                }).then(res => res.json());

Or you could use Promise.all:

const fetchList = file.map(source => {
                var videoPosition = 0;
                var sigkey = "sigkey";
                var formBody = new FormData();
                formBody.set('ver', "1.2");
                formBody.set('key', "key");
                formBody.set('video_id', file[videoPosition].file);
                formBody.set('user_id', "1234");
                formBody.set('format', "json");
                formBody.set('ip', "");
                formBody.set('tts', "0");
                formBody.set('nonce', Math.round((new Date()).getTime() / 1000));

                var sign_fields = [formBody.get('video_id'), formBody.get('user_id'), formBody.get('ip'), formBody.get('tts'), formBody.get('ver'), formBody.get('key'), formBody.get('nonce')];
                var data = sign_fields.join(':');
                var signature = hmacsha256(data, sigkey);

                formBody.set('sig', signature);

                var formBodyStringified = new URLSearchParams(formBody).toString();

                const request = fetch(Config.api.livebox, {
                    method: 'POST',
                    body: formBodyStringified,
                    headers: {
                        'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
                    }
                }).then(res => res.json());
return request;
 });

const resJsons = Promise.all(fetchList);
resJsons.forEach(resJson => {
                const finalJsonUrl = 'https:' + resJson.hls;
                this.setState({ videoSource: finalJsonUrl });
                ...
}
Sign up to request clarification or add additional context in comments.

7 Comments

But do be aware this will execute all mapped elements in parallel. And also loses error handling.
I suppose that's what the PO wanted judging from the code. If concurrency is a problem I would use a promise.all
I would have use file.map( async (source) => { 'cuz its more clear that we define a function
you'd have a better performance but like @Keith mentioned you'd have a problem if it's not managed well.
Without some effort to limit concurrency, this could be fairly catastrophic.
|
0

You use await in this line:

const resJson = await fetch(Config.api.livebox) 

but is not correct usage. because parent function is map callback function and it not async!.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.