最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Do multiple .fetch() promises - Stack Overflow

programmeradmin3浏览0评论

I want to fetch multiple images and turn them in blob. I'm a newbie about promises, I've tried but I can't get through.

Here below, a single .fetch() promise

fetch('/?u=.jpg')
    .then(function(response) {
        return response.blob();
    })
    .then(function(myBlob) {
        var objectURL = URL.createObjectURL(myBlob);
        document.getElementById('myImage').src = objectURL;
    });

Now multiple .fetch() promise (don't work)

var promises = [];

for (var i = values.length - 1; i >= 0; i--) {
    promises.push(fetch(values[i]));
}

Promise
    .all(promises)
    .then(function(response) {
        for (var i = response.length - 1; i >= 0; i--) {
            return response[i].blob();
        }
    })
    .then(function(blob) {
        console.log(blob.length); //undefined !!!
        for (var i = blob.length - 1; i >= 0; i--) {
            console.log(blob[i]);
            lcl_images[i].value = URL.createObjectURL(blob[i]);
            document.getElementById(lcl_images[i].id).src = objectURL;
        }
    })
    .catch(function(error) {
        console.log(error);
    });

I want to fetch multiple images and turn them in blob. I'm a newbie about promises, I've tried but I can't get through.

Here below, a single .fetch() promise

fetch('http://cors.io/?u=http://alistapart./d/_made/d/ALA350_appcache_300_960_472_81.jpg')
    .then(function(response) {
        return response.blob();
    })
    .then(function(myBlob) {
        var objectURL = URL.createObjectURL(myBlob);
        document.getElementById('myImage').src = objectURL;
    });

Now multiple .fetch() promise (don't work)

var promises = [];

for (var i = values.length - 1; i >= 0; i--) {
    promises.push(fetch(values[i]));
}

Promise
    .all(promises)
    .then(function(response) {
        for (var i = response.length - 1; i >= 0; i--) {
            return response[i].blob();
        }
    })
    .then(function(blob) {
        console.log(blob.length); //undefined !!!
        for (var i = blob.length - 1; i >= 0; i--) {
            console.log(blob[i]);
            lcl_images[i].value = URL.createObjectURL(blob[i]);
            document.getElementById(lcl_images[i].id).src = objectURL;
        }
    })
    .catch(function(error) {
        console.log(error);
    });
Share Improve this question edited Jun 24, 2016 at 15:35 FrancescoN asked Jun 24, 2016 at 15:02 FrancescoNFrancescoN 2,17612 gold badges36 silver badges48 bronze badges 5
  • So what does the .blob() method return, a blob or a promise? – Roamer-1888 Commented Jun 25, 2016 at 9:46
  • .blob() returns a blob(), but if you're doing multiple promise, you have to return Promise.all(blobs) in .then(response). After this, in .then(blob) -> blob is array of blob objects – FrancescoN Commented Jun 25, 2016 at 10:32
  • OK, so if .blob() is synchronous, then you don't need two .thens. Promise.all(promises).then(function(responses) {...}).catch(...);will do the job without ever needing to create an array of blobs. – Roamer-1888 Commented Jun 25, 2016 at 11:00
  • if you try yourself this won't work, I'm a newbie about promise. I've tried several times doing what you said, but you have to return the promise response[i].blob() and in the next .then you'll have the blob object. – FrancescoN Commented Jun 26, 2016 at 10:10
  • 1 I'll write an answer for you. – Roamer-1888 Commented Jun 26, 2016 at 11:50
Add a ment  | 

2 Answers 2

Reset to default 7

It is a general rule that a wholly synchronous intermediate step in the success path of a promise chain can be amalgamated with the next step, allowing one then() to be omitted from the chain.

There is actually a proviso on that statement, involving intermediate catches, but it will suffice for this answer.

So, if the .blob() method is geuinely synchronous (it returns a value), only one .then() is required, not two.

Here are two approaches, both of which exploit Array.prototype.map(), and both should work (though they will differ under error conditions):

1. Simple .map() with detail in Promise.all()

var promises = values.reverse().map(fetch); // you may need .reverse(), maybe not. I'm not 100% sure.

return Promise.all(promises).then(function(responses) {
    responses.forEach(function(r, i) {
        var imageObj = lcl_images[i],
            element = document.getElementById(imageObj.id);
        imageObj.value = URL.createObjectURL(r.blob());
        if(element) { //safety
            element.src = imageObj.value;
        }
    });
    return responses; // here, return whatever you want to be made available to the caller.
}).catch(function(error) {
    console.log(error);
});

If you prefer, you can write :

return Promise.all(values.reverse().map(fetch)).then(function(responses) {
    // ...
});

2. Detail in .map() followed a simple Promise.all()

var promises = values.reverse().map(function(val, i) {
    return fetch(val).then(function(result) {
        var imageObj = lcl_images[i],
            element = document.getElementById(imageObj.id);
        imageObj.value = URL.createObjectURL(result.blob());
        if(element) { //safety
            element.src = imageObj.value;
        }
        return result; // here, return whatever you want to be made available to the caller.
    });
});

return Promise.all(promises).catch(function(error) { // return a promise to the caller
    console.log(error);
}); 

Notes:

  • (1) will fail pletely if any one fetch() fails.
  • (2) will perform all the imageObj.value ... and element.src = ... stuff for all successful fetches even if one or more fetch()... fails. Any single failure will cause Promise.all(promises) to return a rejected promise.
  • (1) or (2) may be more appropriate depending on what you want.
  • There are other error handling possibilities.
  • If neither approach works, then the most reasonable explanation would be that the .blob() method returns a promise, not a value.

You are returning from the then handler after first response, instead what you need to do is to return the list of blobs:

Promise
.all(promises)
.then(function(response) {
    // CHANGED HERE
    var blobPromises = [];
    for (var i = response.length - 1; i >= 0; i--) {
        blobPromises.push(response[i].blob());
    }
    return Promise.all(blobPromises);
})
.then(function(blob) {
    console.log(blob.length);
    for (var i = blob.length - 1; i >= 0; i--) {
        lcl_images[i].value = URL.createObjectURL(blob[i]);
        document.getElementById(lcl_images[i].id).src = objectURL;
    }
})
.catch(function(error) {
    console.log(error);
});
发布评论

评论列表(0)

  1. 暂无评论