Home > Back-end >  API call returns image after I render the components
API call returns image after I render the components

Time:01-15

I'm using g-s-i a npm package to make calls to google images.

I'm unable to make this API call and, just after, render the application. I'm aware this has to do with async, but I have no idea how to use it here. I have tried many things with the function imageSearch, but nothing has worked.

I thank if someone can show me a solution to my problem.

My MWE:

HTML:

<!doctype html>
<html  lang="">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="x-ua-compatible" content="ie=edge">
        <title>Debug example</title>
        <meta name="description" content="">
        <meta name="viewport" content="width=device-width, initial-scale=1">

        <link rel="apple-touch-icon" href="/apple-touch-icon.png">
        <!-- Place favicon.ico in the root directory -->

    </head>
    <body>
        <h1>Debugger example</h1>
        <div id="main">
        </div>
    </body>
    <script type="module" src="./dist/bundle.js">
    </script>
</html>

JS:

var gis = require('g-i-s'); // search images from google https://www.npmjs.com/package/g-i-s

var main = document.querySelector("#main")

// Query examples
var searchTopics = [
  {
    searchTerm: 'sleep',
    queryStringAddition: '&tbs=ic:trans'
  },
  {
    searchTerm: 'pony',
    queryStringAddition: '&tbs=ic:trans',
    filterOutDomains: ['deviantart.net', 'deviantart.com']
  }
];

var imageSearch = (query) => {
  let response = [];
  gis(query, (error, results) => {
    console.log(results[1].url)
    response.push(results[1].url)
      }
  )
  return response;
};

// =results= look like:
// [
//   {
//     "url": "https://i.ytimg.com/vi/mW3S0u8bj58/maxresdefault.jpg",
//     "width": 1280,
//     "height": 720
//   },
//   {
//     "url": "https://i.ytimg.com/vi/tntOCGkgt98/maxresdefault.jpg",
//     "width": 1600,
//     "height": 1200
//   },
//   (...)
// ]


var imageLayout = (title) =>
    ((src) => {let e = document.createElement("div")
              e.innerHTML = title
              let img = document.createElement("img")
              img.src = src
              e.appendChild(img)
              return e})

var render = (queries) => {
  queries.forEach((query) =>{

    let img = imageSearch(query)
    console.log(img)

    main.appendChild(imageLayout(query.searchTerm)(img[0]))
  })}

render(searchTopics)

NPM:

npm init
npm install g-i-s

npm install --save-dev browserify @babel/core @babel/preset-env babelify

browserify js/main.js > ./dist/bundle.js -t babelify
watchify js/*.js -o ./dist/bundle.js -d

What happens in my browser: enter image description here

CodePudding user response:

Your imageSearch function calls gis() which doesn't successfully create the response object until the callback passed as the second parameter to gis() is called. However, you're immediately returning the empty response array.

Instead, pass a callback in to imageSearch that gets called when gis() returns, something like this:

const imageSearch = (query, cb) => {
  gis(query, (error, results) => cb(error, results[1].url));
};

const render = (queries) => {
  queries.forEach((query) => {
    let img = imageSearch(query, (error, img) => {
      if (error) {
        console.log("An error happened: ", error);
        return;
      }

      main.appendChild(imageLayout(query.searchTerm)(img))
    });
  });
};

You could also move on to using Promises but that's a different matter, and would not largely change the outcome of the code, just the format of it.

  •  Tags:  
  • Related