-3

A promise is a

(...) value which may be available now, or in the future, or never (Source: MDN)

So lets say I have an app which wants to work with pictures. The pictures are loaded e.g. after an algorithm works with it in the background (or some other sort of delay). Now I want to check, if the pictures are available in the future, by using a promise, not a callback.

To check, if an image is available, I could use the following code:

function loadImage(url) {
  return new Promise((resolve, reject) => {
    let image = new Image()

    image.onload = function() {
      resolve(image)
    }

    image.onerror = function() {
      let message =
        'Could not load image at ' + url
      reject(new Error(msg))
    }

    image.src = url
  })
}

The promise, which belongs to this would look something like this:

Promise.all([
  loadImage('images/pic1.jpg'),
  loadImage('images/pic2.jpg')
]).then((images) => {
  images.forEach(img => addImg(img.src))
}).catch((error) => {
  // handle error 
})

This will not help my at all, because the promise will look up if the pictures are available in the present, not in the future. The pictures will be there in a second, still the promise will return an error.

What do I not get about promises here? For me it looks like the entire future aspect of checking, if the pics are available depends on loadImage(url) not on the actual promise itself.

PS: Example inspired by funfunfunction


How would the promise know when it is resolved?

To my understanding it does not "listen" to the other code around it, let alone a framework which might run in the background. I would assume in this example it would turn out like this: promise checks if pictures are available -> they are still worked with in the background -> promise resolves and throws error -> algorithm is finished with pictures -> pictures are available ?

guest271314
  • 1
  • 15
  • 104
  • 177
User12547645
  • 6,955
  • 3
  • 38
  • 69
  • _"still the promise will return an error."_ Where is an error at `javascript` at Question? – guest271314 May 15 '17 at 15:03
  • **pls note that this is hypothetical!** I know there are other ways to solve this problem. I would like to understand how promises could help me here and and why everything seems to depend on loadImage(url), not on the promise itself – User12547645 May 15 '17 at 15:04
  • 3
    *because the promise will look up if the pictures are available in the present, not in the future.* - the thing about the future is that it has a habit of eventually becoming the present. – Matt Burland May 15 '17 at 15:04
  • 4
    [You're Missing the Point of Promises](https://gist.github.com/domenic/3889970). The `Promise` only facilitates the task to be performed. Using `Promise` does not exempt the developer from composing and maintaining proper logic and error handling within code. – guest271314 May 15 '17 at 15:04
  • The promise will return an error and will go to `// handle error`, since the images are not available right now. They will be available in the future. – User12547645 May 15 '17 at 15:05
  • A promise is just a way of not blocking on an operation which takes some time, not a way to detect when something can be done (such as when the image is available). – Domino May 15 '17 at 15:06
  • What do you mean by _"since the images are not available right now. They will be available in the future."_? `Promise` is not necessary to return expected result. You can check the `.length` of an array to determine if loaded images are equal to original list of URLs to fetch. – guest271314 May 15 '17 at 15:07
  • They will will be available in the future, after the background algorithm in finished with it. I am checking in the present. In the present they are not jet available.@guest271314 – User12547645 May 15 '17 at 15:09
  • @User12547645 Are you referencing `addImg()` function call at `images.forEach(img => addImg(img.src))`? Or `loadImage()` call? – guest271314 May 15 '17 at 15:11
  • @guest271314 No. It is not important what is loaded. I want to understand promises. This is not about loading images – User12547645 May 15 '17 at 15:13
  • Please understand that the arguments to `then` and `catch` are callback functions that are *never executed immediately*, but always asynchronously after the promises resolve. Even if the code is nicely compacted together does not mean all of it executes immediately. Some of it executes somewhere in the future, and only then will you maybe get an error or a success. – trincot May 15 '17 at 15:18
  • @trincot Thank you very much! Still a question remains. How would the promise know when it is resolved. To my understanding it does not "listen" to the other code around it, let alone a framework which might run in the background. I would assume in this example it would turn out like this: promise checks if pictures are available -> they are still worked with in the background -> promise resolves and throws error -> algorithm is finished with pictures -> pictures are available – User12547645 May 15 '17 at 15:20
  • @trincot Not sure how the linked Question resolves current Question specific to `Promise` usage? – guest271314 May 15 '17 at 15:25
  • The DOM will call the `onload` callback once the image is loaded (so not immediately). In your code you have made it that at that moment also your promise resolves, which will trigger the callback you have passed to `then`. In case the DOM cannot load the image due to some error, the `onerror` callback will be called. That is when you reject the promise, which will trigger the callback passed to `catch`. So the waiting really happens in the DOM internals. Your code depends on the fact that you know eventually either `onload` or `onerror` will be called (asynchronously). – trincot May 15 '17 at 17:03

1 Answers1

2

What is the point of promises in JavaScript?

See: You're Missing the Point of Promises.


Cannot consider all of the nuances relevant to using Promise alone. Browse the promise tag to read other users' questions and answers posted by users whom post frequently at promise tag. Ask questions as to specific cases at comments at those questions and answers, for your own edification.


You get the value of a Promise using .then() or .catch(), not by checking the value of a variable outside of Promise chain.

Disregard "present" and "future". Focus on implementing code within .then() and, or .catch(). All other code referencing an asynchronous value referenced by an identifier will not be reliable.

let id = void 0;

let promise = new Promise(resolve => 
                setTimeout(() => {id = 123; resolve(id) }, Math.random() * 2000)
              );

// this is not accurate
console.log(`id: ${id}`); // what is `id` here?

promise.then(res => console.log(`id: ${res}`));

Note also, function passed to Promise constructor as executor is called immediately

let id = void 0;

let promise = new Promise(resolve => 
                setTimeout(resolve, Math.random() * 2000, id = 123)
              );

// is this accurate?
console.log(`id: ${id}`); // what is `id` here?

promise.then(res => console.log(`id: ${res}`));

return a value from .then().

return a value from .then(). Use .map() instead of .forEach()

Promise.resolve(123)
.then(data => console.log(data))
.then(res => console.log(res)) // `undefined`

Promise.resolve(123)
.then(data => { console.log(data); return data})
.then(res => console.log(res)) // `123`

Use .map() instead of .forEach()

let fn = (id) =>  new Promise(resolve => 
                    setTimeout(resolve, Math.random() * 2000, id)
                  );
                  
Promise.all([1,2,3].map(fn))
.then(data => Promise.all(data.forEach(id => fn(id * 10))))
.then(data => console.log(`data: ${data}`)); // where is `data`

                  
Promise.all([1,2,3].map(fn))
.then(data => Promise.all(data.map(id => fn(id * 10))))
.then(data => console.log(`data: ${data}`)); // `[10, 20, 30]`

A handled rejection or error is converted to a resolved Promise is not thrown or rejection returned

let fn = () => new Promise((resolve, reject) => 
                setTimeout((id) => {reject(new Error(id)) }, Math.random() * 2000, 123)
              )

fn().then(res => console.log(`id: ${res}`))
.catch(err => console.log(`err: ${err}`))
.then(res => console.log(`res: ${res}`)) // `undefined`

fn().then(res => console.log(`res: ${res}`))
.catch(err => { console.log(`err: ${err}`); return err })
// `.then()` is not called, function passed to `.catch()` is called
.then(res => console.log(`res: ${res}`)) 
.catch(err => console.log(`err: ${err}`)) // `123`
guest271314
  • 1
  • 15
  • 104
  • 177