2016-07-25 5 views
5

Прежде всего, я должен признаться, что здесь есть несколько десятков подобных вопросов в stackoverflow (this, this и множествах других), но все они прекрасно решены с помощью функцию обратного вызова, или просто положить код внутри этого image.onload события:Как вернуться после загрузки изображения

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

Но это не мой случай. Это подпись моей функции, которая отвечает за загрузку изображений:

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 
} 

Итак, мне нужно вернуться! Я должен это сделать, и у меня нет другого шанса. Причина, почему я должен следовать этой подписи является то, что эта модель используется какой-либо внешняя библиотечной функцией, которая выглядит так:

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

Таким образом, даже если я могу изменить логику моей patternBuilder функции, я до сих пор не могу изменить функция внешней библиотеки. Эта внешняя функция использует patternBuilder и возвращает сама переменная стиля. Таким образом, нет места для обратных вызовов.

+0

Вы можете предварительно загрузить изображения перед тем, как начать создание шаблона? – Icepickle

+0

Вы можете увидеть параметр 'index', переданный' patternBuilder'. Таким образом, эти изображения создаются динамически, и я не знаю заранее, каковы все эти образы. Их теоретически могут быть сотни. Поэтому мне нужно загрузить изображение, только когда оно мне понадобится. – Jacobian

+0

Можете ли вы поместить свой код в jsfiddle или codepen, это так беспорядочно, чтобы получить что-то от ваших кодов здесь. Спасибо – ristapk

ответ

1

Вот как это может работать с обещаниями

простой обертку, чтобы вернуть изображение обещания:

//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; 
    }); 
} 

и ваш 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]; 
} 

и функции вы используете шаблон:

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 
      }) 
     }) 
    }) 
} 
+0

Это выглядит великолепно. Я попробую. – Jacobian

+0

Я попробовал. Я не так хорошо разбираюсь в JavaScript Promises, поэтому я не знаю, что с этим не так, и как с этим справиться, но теперь функция 'style' возвращает' Promise {: "ожидающий"} 'объект вместо стиль объекта. И это приводит к другим ошибкам. – Jacobian

+0

@Jacobian True, теперь вам нужно обновить элементы, которые используют функцию «стиль», чтобы обрабатывать ее как обещание, а также использовать ключевое слово «then» – Icepickle

0

Вы пробовали использовать обещание? Вы можете контролировать обратный вызов, поэтому, когда изображение загружено, вы можете вернуть функцию.

+1

это должно быть комментарий в текущем состоянии – MJB

+0

Извините, я думал, что я не могу комментировать! – dbmdlr

+0

@dbmdlr Если вы еще не можете комментировать, вы можете начать с редактирования некорректных сообщений, чтобы получить репутацию и/или дать некоторые (хорошие) ответы на вопросы, на которых вы можете дать хорошие ответы, получить репутацию для публикации комментариев относительно легко. do – Icepickle

Смежные вопросы