How to return after image upload

First of all, I have to admit that there are dozens of similar issues here in stackoverflow ( this , this, and myriads of others), but all of them are well resolved using the callback function or just put the code inside this image.onload event:

 image.onload = function () { //do other stuff that should be done right after image is loaded } 

But this is not my business. This is the signature of my function, which is responsible for loading images:

 function patternBuilder (index) { var pattern, image, ... ... image = new Image(); image.id = "_" + index + "_"; image.src = "images/_" + index + "_.png"; image.onload = function () { pattern = ctx.createPattern(image, "repeat"); } return pattern; // !!!! may return undefined if image is not yet loaded } 

So I need to come back! I have to do this, and I have no other chance. The reason I should follow this signature is because this template is used by some external library function that looks like this:

 style: function (feature) { var pattern = patternBuilder(feature.get("index")); var style = new ol.style.Style({ fill: new ol.style.Fill({ color: pattern }) }); return style; } 

So, even if I can change the logic of my patternBuilder function, I still cannot change the external library function. This external function uses patternBuilder and returns the style variable itself. Thus, there is no possibility for callbacks.

+5
source share
2 answers

Here's how it could work with promises

simple wrapper for image return promises:

 //takes an url and returns a promise of a (loaded) Image. function getImage(url){ return new Promise(function(){ var image = new Image(); image.onload = function(){ resolve(image); }; image.onerror = reject; //TODO: resolve that to sth. better image.src = url; }); } 

and your patternBuilder

 function patternBuilder (index) { //returns now a pattern-promise return getImage( "images/_" + index + "_.png" ).then(function(image){ //image.id = "_" + index + "_"; //what exactly is this ID for? return ctx.createPattern(image, "repeat"); }); } //you may want to add some caching var patternCache = Object.create(null); function patternBuilder(index) { if(!patternCache[index]){ patternCache[index] = getImage( "images/_" + index + "_.png" ).then(image => ctx.createPattern(image, "repeat")); } //still returns pattern-promise, but some may have been resolved a "long time" ago. return patternCache[index]; } 

and the function that you use the template:

 style: function(feature) { //returns a style-promise return patternBuilder(feature.get("index")).then(function(pattern){ return new ol.style.Style({ fill: new ol.style.Fill({ color: pattern }) }) }) } 
+1
source

Did you try to use the promise? You can control the callback, so when the image is uploaded, you can return the function.

0
source

All Articles