javascriptreactjsaxiosgoogle-booksgoogle-books-api

Making api requests on an array of objects using async/await and Promise.all()


I'm creating a simple book search app, I make an initial api request to get an array of book objects, then I need to make an api request on each individual book to get the dimensions. When I console.log the initial array of books the book objects have the added attribute('height'), but I believe it is because the array is updated after I make my api calls. Then when I console.log the array after I make the individual api calls I'm given an array of promises. Last when I Promise.all() the array of promises they all come back undefined. I've been playing around with async/await for a bit and would appreciate any tips or feedback you think would help me figure out how to be able to return an array of my books with the "height" attribute I add in the individual api calls.

    
    searchBook = (event) => {
    event.preventDefault();
    axios
      .get(
        "https://www.googleapis.com/books/v1/volumes?q=" +
          this.state.searchField +
          "&key=" +
          this.state.apiKey
      )
      .then((data) => {
        //fill in missing attributes
        const cleanData = this.cleanData(data.data.items);

        //filter books for specific author
        const filterAuthor = this.filterAuthor(cleanData);

        //add height attribute to book
        const addHeight = this.addHeight(filterAuthor);

        console.log(filterAuthor); //returns array of book objects

        console.log(addHeight); //returns array of promises

        Promise.all(addHeight).then((data) => {
          console.log(data); //returns array of undefined
        });
        //this.setState({ books: addHeight }); 
      });
  };

  //add 'height' attribute to book objects
  addHeight = (data) => {
    const addHeight = data.map(async (book) => {
      await axios
        .get(
          "https://www.googleapis.com/books/v1/volumes/" +
            book.id +
            "?key=" +
            this.state.apiKey
        )
        .then((data) => {
          if (data.data.volumeInfo?.dimensions) {
            book["height"] =
              data.data.volumeInfo.dimensions.height.split(" ")[0] / 2.54; //convert cm to in
          } else {
            book["height"] = "0";
          }
          return book;
        });
    });
    return addHeight;
  };

Solution

  • TLDR

    The way I see it, you need to return promise(I mean need to return axios

    Answer

    I think there is no return value in promise object. when you use async/await at const addHeight = data.map(async (book)=> {...}) this callback can't return anything. So when you return axios, your promise can get right data

    Example

     addHeight = (data) => {
        const addHeight = data.map((book) => {
         return axios
            .get(
              "https://www.googleapis.com/books/v1/volumes/" +
                book.id +
                "?key=" +
                this.state.apiKey
            )
            .then((data) => {
              if (data.data.volumeInfo?.dimensions) {
                book["height"] =
                  data.data.volumeInfo.dimensions.height.split(" ")[0] / 2.54;
              } else {
                book["height"] = "0";
              }
              return book;
            });
        });
        return addHeight;
      };