54

I searched about this but I didn't find anything specific for what I need. If there is one, please, share here.

I'm trying to create a generic service to be called in various components. Since it's a function that requests data from an external source, I need to treat it as an asynchronous function. Problem is, the editor returns the message "'await' has no effect on the type of this expression". And the app indeed crashes since there is no data yet.

People.js calls the service requests.js

import React, { useEffect, useState } from "react";
import requests from "../services/requests";

export default () => {

   // State
   const [ people, setPeople ] = useState({ count: null, next: null, previous: null, results: [] });

   // Tarefas iniciais
   useEffect(() => {
       carregarpeople(1);
   }, []);

   // Carregando os dados da API
   const carregarpeople = async (pageIndex) => {
       const peopleResponse = await requests("people", pageIndex);

       // This line below needs to be executed but it crashes the app since I need to populate it with the data from the function requests
       // setPeople(peopleResponse);
   }


   return (
       <div>
       {
           people.results.length > 0 ? (
               <ul>
                   {
                       people.results.map(person => <li key = { person.name }>{ person.name }</li>)
                   }
               </ul>    
           ) : <div>Loading...</div>
       }
       </div>
   )
  }

And this is requests.js, where it returns the json from API

export default (type, id) => {
console.table([ type, id ]);

fetch(`https://swapi.co/api/${type}/?page=${id}`)

.then(response => response.json())
.then(json => {
    console.log(json);
    return json;
})}

enter image description here

Emile Bergeron
  • 17,074
  • 5
  • 83
  • 129
Raphael Alvarenga
  • 868
  • 1
  • 7
  • 13

4 Answers4

89

I was getting this error just because my JSDoc comment was incorrect.

For example I had an async function that had @returns {string}:

  /**
   * Fetch from the swapi API
   *
   * @param {string} type
   * @param {string} id
   * @returns {string} JSON
   */
  export default async (type, id) => {
    console.table([ type, id ]);
    const response = await fetch(`https://swapi.co/api/${type}/?page=${id}`);
    const json = await response.json();
    console.log(json);
    return json;
  }

I was getting the "'await' has no effect on the type of this expression" warning - but the function looked correct.

However once I changed the JSDoc to @returns {Promise<string>} then the error disappeared:

  /**
   * Fetch from the swapi API
   *
   * @param {string} type
   * @param {string} id
   * @returns {Promise<string>} JSON
   */

You can also use the @async hint as the JSDoc documentation suggests:

/**
 * Download data from the specified URL.
 *
 * @async
 * @function downloadData
 * @param {string} url - The URL to download from.
 * @returns {Promise<string>} The data from the URL.
 */
icc97
  • 11,395
  • 8
  • 76
  • 90
  • 12
    This answer was helpful for me. Though it does not apply to the problem in question, it was nonetheless the solution for my issue. Thanks for posting. – qslabs Mar 11 '21 at 15:11
  • 2
    Wow, incredible... Thank you so much. But I have to ask, why on earth would it rely on what I wrote in comments, instead of what is actually returned? Really odd, thanks again though! – Chrimle Mar 24 '22 at 18:20
  • 1
    @Chrimle its because the code doesn't know what the return type is so it relies on the doc blocks to guess the type – icc97 Mar 24 '22 at 18:49
  • 1
    Thanks for the clarification. I had no idea, I just recently picked up on adding JSDocs to my various methods and didn't take it that seriously - I guess I have to from now on! – Chrimle Mar 24 '22 at 18:59
  • 1
    @Chrimle you can also switch to typescript that has better knowledge of the types you use – icc97 Mar 24 '22 at 19:19
  • You saved me a similar question :) Changed my comment and it's solved. – Or Assayag Feb 25 '23 at 18:17
31

await is only useful if you use it with a promise, but requests does not return a promise. It doesn't have a return statement at all, so it's implicitly returning undefined.

Looks like you meant for it to return a promise, so here's your code with the return added in:

export default (type, id) => {
  console.table([ type, id ]);
  return fetch(`https://swapi.co/api/${type}/?page=${id}`)
    .then(response => response.json())
    .then(json => {
      console.log(json);
      return json;
    })
}

p.s, if you prefer to do this using async/await, it would look like:

export default async (type, id) => {
  console.table([ type, id ]);
  const response = await fetch(`https://swapi.co/api/${type}/?page=${id}`);
  const json = await response.json();
  console.log(json);
  return json;
}
Nicholas Tower
  • 72,740
  • 7
  • 86
  • 98
  • 1
    Great. This is the solution. I thought the "return json" line that was already there was the return. But the return must be before fetch. Thanks Nicholas! – Raphael Alvarenga Feb 24 '20 at 00:31
3

if you are getting this with typescript, maybe it's because you're not returning a Promise

for example:
❌incorrect:

async delPerson (id: string): Partial<Person> {
    return await this.personModel.findByIdAndRemove(id);
}
deletedPerson = await this.personService.delPerson(body._id);
// in above line typescript thinks that he is awaiting for something which is not a promise

✅correct:

async delPerson (id: string): Promise<Partial<Person>> {
    return await this.personModel.findByIdAndRemove(id);
}
deletedPerson = await this.personService.delPerson(body._id);
0

I found the solution. This suggestion pops up because you have put a wrong object after await. You can completely get rid of this by putting a promise (without brackets) or a function that returns a promise after the await keyword.

ZyadOmer999
  • 117
  • 1
  • 10