Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bluebird's Promise.settle doesn't resolve with the correct values

I have the following code:

return Promise.settle(matches, imgur.uploadUrl)
    .map(function (inspection) {
        if (inspection.isFulfilled()) {
            return inspection.value().data.link;
        }
        return '#';
    })

A more verbose version of the above displays the same problems:

return Promise.settle(matches, function(match) { return imgur.uploadUrl(match); })
    .then(function(results) {
        return results;
    })
    .map(function (inspection) {
        if (inspection.isFulfilled()) {
            return inspection.value().data.link;
        }
        return '#';
    })

Where

  • Promise = bluebird's promise
  • matches = an array of image links extracted from a string
  • imgur = https://github.com/kaimallea/node-imgur

The expected behavior is that the result of .map is a promise which resolves with an array of imgur links after the images in the original array was uploaded to imgur (or '#', in case the upload failed for any reason).

What happens instead is that Promise.settle resolves instantly (i.e. doesn't seem to wait for the imgur uploads), and inspection.value() is the original image url from the matches array (which gives an error when trying to read the .data.link property of a string).

Why does this happen? Why won't it upload to imgur and resolve correctly?

like image 908
Madara's Ghost Avatar asked Feb 11 '23 17:02

Madara's Ghost


2 Answers

When I look at the Bluebird source for Promise.settle(), I only see that it processes the first argument (expecting an array of promises). I've always just used it as a substitute for Promise.all() when you want all promises to complete, even if some have errors.

I wonder if the Bluebird documentation for .settle() is just wrong about it taking a function as the second argument that will process the first array? The code is a little hard to follow, but I don't see how Promise.settle() ever uses the 2nd argument (unless this isn't the right code I'm looking at for some reason).

As you pointed out, an alternative is:

Promise.settle(matches.map(imgur.uploadUrl)).then(...)

which just passes an array of promises to .settle().


FYI, I verified by creating a simple test case and stepping into Promise.settle() in the debugger that it never uses the second argument passed to it. This appears to be a case of the documentation not matching the implementation. I expect someone planned to implement what is documented, but never completed that implementation.

like image 141
jfriend00 Avatar answered Feb 14 '23 06:02

jfriend00


This was indeed a bug in the docs. It was fixed (props to OP for the pull request).

The docs now show the correct usage of .settle.

like image 27
Benjamin Gruenbaum Avatar answered Feb 14 '23 06:02

Benjamin Gruenbaum