Search code examples
javascriptreactjspromisees6-promise

React call API filter out undefined promises


I'm trying to figure out how to map over an API call.

The scenario is that an API gets called that returns a promise. This promise could include objects that are undefined, I want to skip these objects and only add working objects into a state called `searchResult``

Here are two failed attempts

1:

onSearch = (query) => {
    if(query){
    BooksAPI.search(query).then((searchResult) => {
      if(typeof searchResult !== 'undefined') {
        console.log(searchResult)
        searchResult.map((books) => {
          books.shelf = this.state.bookShelfMapping[books.id] ?
          this.state.bookShelfMapping[books.id] : 'none'
        })
        // Check if users changes searchResult
        if(this.state.searchResult !== searchResult) {
          this.setState({searchResult})

        }
      } else {
        continue
      }
    }).catch( e => console.log(e))
  }
}

2:

onSearch = (query) => {
    if(query){
    BooksAPI.search(query).then((searchResult) => {
      if (Array.isArray(searchResult)) {
        searchResult.map((books) => {
          books.shelf = this.state.bookShelfMapping[books.id] ?
          this.state.bookShelfMapping[books.id] : 'none'
        })
        // Check if users changes searchResult
        if(this.state.searchResult !== searchResult) {
          this.setState({searchResult})

        }
      } else {
        this.setState({searchResults: []})
      }
    }).catch( e => console.log(e))

EDIT ADDED A third try:

onSearch = debounce((query) => {
    console.log("In onSearch()")
    BooksAPI.search(query)
    .then((searchResult) => {
      console.log(searchResult)
      console.log("In onSearch() first .then")
      if(!Array.isArray(searchResult)) {
        throw new Error('Bad response')
      }
    })
    .then((searchResult) => {
      console.log("In onSearch() second .then")
      if (typeof searchResult !== 'undefined' && Array.isArray(searchResult)) {
        console.log("In onSearch() second .then if statement")
        searchResult.map((books) => {
          books.shelf = this.state.bookShelfMapping[books.id] ?
          this.state.bookShelfMapping[books.id] : 'none'
        })

        this.setState({searchResult})

      }
    })
    .catch( e => {
      console.log("in onSearch .catch")
      console.log(e)
    })
    console.log(this.state.searchResult)
  }, 300)

So as shown above a BooksAPI is called with a query ( retrieved from an input) this returns the promise I want to reject undefined objects from.

Example of working object from postman

{
    "books": [
        {
            "title": "Taijiquan Classics",
            "subtitle": "An Annotated Translation",
            "authors": [
                "Barbara Davis",
                "Weiming Chen"
            ],
            "publisher": "North Atlantic Books",
            "publishedDate": "2004",
            "description": "Along with Chinese art, medicine, and philosophy, taijiquan has left the confines of its original culture, and offers health, relaxation, and a method of self-defense to people around the globe. Using the early texts now known as The Taijiquan Classics which have served as a touchstone for t’ai chi practitioners for 150 years, this book explores the fundamental ideas and what they mean to practitioners, students, and scholars. It also incorporates newly discovered sources that address the history of taijiquan and newly translated commentaries by Chen Weiming.",
            "industryIdentifiers": [
                {
                    "type": "ISBN_10",
                    "identifier": "1556434316"
                },
                {
                    "type": "ISBN_13",
                    "identifier": "9781556434310"
                }
            ],
            "readingModes": {
                "text": false,
                "image": false
            },
            "pageCount": 212,
            "printType": "BOOK",
            "categories": [
                "Health & Fitness"
            ],
            "maturityRating": "NOT_MATURE",
            "allowAnonLogging": false,
            "contentVersion": "0.0.1.0.preview.0",
            "panelizationSummary": {
                "containsEpubBubbles": false,
                "containsImageBubbles": false
            },
            "imageLinks": {
                "smallThumbnail": "http://books.google.com/books/content?id=vOoexFHEKXgC&printsec=frontcover&img=1&zoom=5&edge=curl&source=gbs_api",
                "thumbnail": "http://books.google.com/books/content?id=vOoexFHEKXgC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api"
            },
            "language": "en",
            "previewLink": "http://books.google.com/books?id=vOoexFHEKXgC&printsec=frontcover&dq=classics&hl=&cd=1&source=gbs_api",
            "infoLink": "http://books.google.com/books?id=vOoexFHEKXgC&dq=classics&hl=&source=gbs_api",
            "canonicalVolumeLink": "https://books.google.com/books/about/Taijiquan_Classics.html?hl=&id=vOoexFHEKXgC",
            "id": "vOoexFHEKXgC",
            "shelf": "none"
        }
    ]
}

Example from rejected

{
    "books": {
        "error": "empty query",
        "items": []
    }
}

Edit : -----

BooksAPI.search(query)
    .then((searchResult) => {
      console.log(searchResult)

Gives me a response first of (first millisecounds)

[]
  length: 0
   __proto__: Array(0)

Followed by a

(20) [Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object]
0
:
Object
allowAnonLogging
:
false
authors
:
Array(2)
averageRating
:
4
canonicalVolumeLink
:
"https://books.google.com/books/about/Best_Android_Apps.html?hl=&id=bUybAgAAQBAJ"
categories
:
Array(1)
contentVersion
:
"preview-1.0.0"
description
:
"Contains descriptions of over two hundred recommended applications and games for android/mobile devices, including apps for business, communication, lifestyle, entertainment, utility/tool, and reference."
id
:
"bUybAgAAQBAJ"
imageLinks
:
Object
industryIdentifiers
:
Array(2)
infoLink
:
"http://books.google.com/books?id=bUybAgAAQBAJ&dq=android&hl=&source=gbs_api"
language
:
"en"
maturityRating
:
"NOT_MATURE"
pageCount
:
240
previewLink
:
"http://books.google.com/books?id=bUybAgAAQBAJ&dq=android&hl=&cd=1&source=gbs_api"
printType
:
"BOOK"
publishedDate
:
"2010-04-27"
publisher
:
""O'Reilly Media, Inc.""
ratingsCount
:
3
readingModes
:
Object
shelf
:
"currentlyReading"
subtitle
:
"The Guide for Discriminating Downloaders"
title
:
"Best Android Apps"
__proto__
:
Object

Would appreciate some input on how to proceed. Cheers!


Solution

  • For this purpos I ended up with a solution like this.

    onSearch = debounce((query) => {
    
          BooksAPI.search(query).then((searchResults) => {
            if (!searchResults || searchResults.error){
              this.setState({searchResult : []})
              return searchResults
            } else if (Array.isArray(searchResults)) {
    
                searchResults.map((book) => {
                  book.shelf = this.state.bookShelfMapping[book.id] ?
                  this.state.bookShelfMapping[book.id] : 'none'
                  return searchResults
    
                })
    
                if (this.state.searchResults !== searchResults) {
    
                  this.setState({searchResult : searchResults})
    
                }
            } })
            .catch(e => console.log(e))
        }, 300)
    

    One thing that I missed before was that the searchResult could return both as undefinedand as a .error