Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Promise is returning [object Promise]

I am trying to do a basic check to see if an image is retina and has a portrait ratio. I have all that checking functionality working perfectly fine. My issue is that in the final function that is supposed to return the boolean I get from my checks it is returning [object Promise]. I have no idea why this is not returning my boolean when I resolve the promise.

When I run .then(res => console.log(res)) it outputs my boolean response, but the function getImageMeta() that returns the promise just returns that [object Promise] which makes me think the promise isn't actually being resolved.

If I could get some assistance that would be great!

/************************************
   Check if image is retina portrait
************************************/
const checkIfPortrait = src => !isRetina(src) ? false : getImageMeta(src).then(res => res);
 const isRetina        = src => src.indexOf('@2x') !== -1;
 const isPortrait      = ({ naturalWidth, naturalHeight }) => naturalHeight > naturalWidth ? true : false;

 function getImageMeta (src) {
    const img = new Image();
    img.src = src;

    return new Promise((resolve, reject) => {
      return img.addEventListener("load", function () {
         return resolve(isPortrait(this));
      }, false);
    });
  }


 export { checkIfPortrait }

This is how I am calling the function:

<img src={media[i].image} alt={media[i].alt} data-portrait={checkIfPortrait(media[i].image)} />
like image 980
Brady Edgar Avatar asked Oct 12 '17 22:10

Brady Edgar


People also ask

Why is my function returning object Promise?

You are getting [object Promise] as value because you are calling an asynchronous function inside a synchronous code. This means the synchronous code runs line by line giving no room for asynchronous code to wait and give a response (the promise).

How do you return objects as promises?

Promise resolve() method: resolve() method in JS returns a Promise object that is resolved with a given value. Any of the three things can happened: If the value is a promise then promise is returned.

What is returned by Promise?

Returns a new Promise object that is resolved with the given value. If the value is a thenable (i.e. has a then method), the returned promise will "follow" that thenable, adopting its eventual state; otherwise, the returned promise will be fulfilled with the value.

Does Promise then return a Promise?

Promise.prototype.then() The then() method returns a Promise . It takes up to two arguments: callback functions for the success and failure cases of the Promise .


Video Answer


3 Answers

This is the expected result. When you return a new Promise object, it will always be a promise object ([object Promise] when stringified).

You access the result of a promise by using the .then method (or using await in an async function). Your .then callback is then called when/if the result is made available, which will happen after you call resolve, or if the promise was already resolved prior it will be called rather quickly.

function getImageMeta(src) {     return new Promise(resolve => {         setTimeout(() => {             resolve({metadata: `for: ${src}`});         }, 100);     }); }  getImageMeta('test.png').then(meta => {     console.log(meta); // {"metadata": "for: test.png"} });  (async () => {     const meta = await getImageMeta('test.png');     console.log(meta); // {"metadata": "for: test.png"} })();
like image 73
Alexander O'Mara Avatar answered Sep 19 '22 17:09

Alexander O'Mara


The basic idea of a promise is that it gives you something to return right away even if it won't resolve until later. It represents its eventual value. So getImageMeta () is immediately returning the promise even though it has not resolved.

Once you have the promise returned by getImageMeta () you can use its then() to wait for the final boolean, which will come on the next event loop cycle at the earliest.

With your current code you are saving the promise returned by getImageMeta() to checkIfPortrait. So now checkIfPortrait holds this promise and you can call then() on it. Since you are exporting checkIfPortrait you will probably end up calling then on the module that imports it:

 // import checkIfPortrait checkIfPortrait(src) .then(ret_val => {    //you can access boolean here in ret_val }) 
like image 35
Mark Avatar answered Sep 23 '22 17:09

Mark


The issue is now resolved, thanks to everyone for the help. Like stated the issue was I was calling the promise's value before it could be resolved and had no way of updating that value after it had been resolved.

So what I did is made sure the image data was accessible before running the function. Then once I had a resolved promise it then update the image data to show whether it is portrait or not.

So the final code looks like this:

const enhance = lifecycle({
   componentWillMount: function () {
     Object.keys(this.props.media).map((i) =>
       checkIfPortrait(this.props.media[i].image)
         ? this.props.media[i].isPortrait = true
         : this.props.media[i].isPortrait = false
       );
   }
 })

const checkIfPortrait = src => !isRetina(src) ? false : getImageMeta(src).then(res => res);
 const isRetina        = src => src.indexOf('@2x') !== -1;
 const isPortrait      = ({ naturalWidth, naturalHeight }) => naturalHeight > naturalWidth ? true : false;

 function getImageMeta (src) {
   const img = new Image();
   img.src = src;

   return new Promise((resolve, reject) => {
     return img.addEventListener("load", function () {
       return resolve(isPortrait(this));
     }, false);
   });
 }


 export { checkIfPortrait }

<img src={media[i].image} alt={media[i].alt} data-portrait={media[i].isPortrait} />
like image 32
Brady Edgar Avatar answered Sep 22 '22 17:09

Brady Edgar