Просмотр полной версии : event.target.loader ошибка #2099 в ioError (мультипоточная загрузка)
Создаю несколько объектов типа loader и каждому присваиваю уникальный name, далее вешаю на contentLoaderInfo слушатели.
Когда срабатывает евент complete, то я могу получить этот name, через event.target.loader.name. А вот когда приходит ioError, так сделать не получается, пишет ошибку #2099.
Может кто то сталкивался, или подскажет каким еще образом узнать какой из лоадеров вызвал евент с ошибкой?
Для начала надо перестать грузить все параллельно.
Если перестать грузить параллельно - не было бы вопроса. Нужна именно МУЛЬТИпоточная загрузка. Причем колличество потоков назначаемо.
Я в цикле создаю несколько лоадеров. Каждый из лоадеров получает из массива объектов свой объект, в котором хранится адрес загрузки и id этого объекта и еще некоторые параметры нужные мне. Этот id назначается в loader.name.
Далее при евенте комплит я получаю этот id, иду в массив, и обрабатываю этот элемент как мне необходимо, после чего лоадеру опять назначаю уже новую загрузку. Сбой происходит когда срабатывает евент еррор, я не могу вытащить необходимый мне id, и не могу найти этот елемент в массиве объектво, для обработки.
Флеш очень плохо переносит параллельную загрузку и в большинстве случаев выполняет её последовательно.
Этот пример превосходно переносит параллельную загрузку - единственная проблема в битых линках ... если бы их не было - не было бы вообще никаких проблем.
Впринципе можно было бы отсечь такие линки и на стороне сервера, проверять заранее, либо давать ответ от сервера, не 404, а какую-то заранее подготовленную картинку, которую я уже внутри флешки мог бы обработать.
Вобщем, я знаю и еще один способ как обойти описанную мной проблему:
Можно для каждого лоадера создать слушатель, с вызовом своего собственного обработчика, но это не рационально, т.к. писать кучу практически одинаковых функций обработки - не практично.
Хотелось бы красивого решения, оставив мультипоточность на своем месте, надеюсь есть кто-то еще из знающих людей, которые могли бы помочь в этом вопросе?
Dendroid
02.06.2007, 15:56
О. А вот и тот пример, описывающий как раз, почему я говорил, что, в частности, статичный ContentLoaderInfo - это плохо.
Смысл-то тот же самый, можно расширить Loader и присвоить ему идентификатор name, но при срабатывании события error, линки из ContentLoaderInfo в Loader ещё нет, конечно будет 2099. Красивое решение могло бы быть, если кто мне скажет-таки как сделать динамичный ContentLoaderInfo, чтобы идентификатор name можно было давать не только в Loader, но и в ContentLoaderInfo. :)
Могу поделится своим некрасивым решением:
private function loadError (e:Event) {
trace(e.text);
for (var i:int=0; i<_loadersN; i+=1) {
if (loaders[i].contentLoaderInfo==e.target) {
loaders[i].state = -1;
}
}
_loadFailed = true;
loadProgress(e);
}
Смысл в чём: храним линки на все лоадеры в массиве, когда возникает error, мы не можем определить какому лоадеру принадлежит ContentLoaderInfo, который сгенерил ошибку изнутри. Но снаружи можем, т.к. каждый лоадер уже имеет ссылку на свой ContentLoaderInfo, надо их просто сравнить в цикле.
Другой вариант (ещё хуже), но работает у меня в двух проектах:
Изнутри ContentLoaderInfo мы можем убивать слушателей, наличие слушателя - это целый бит информации! :) Возникает ошибка ввода-вывода - убиваем слушателя IOErrorEvent.IO_ERROR(removeEventListener), возникает ошибка доступа - убиваем слушателя SecurityErrorEvent.SECURITY_ERROR, нормально загрузилось - убиваем Event.COMPLETE.
По окончании загрузки пробегаем по всем лоадерам, и по наличию слушателей (hasEventListener) определяем, кто как кончил. :)
Да нормально Флэш грузит по крайней мере до 100 файлов параллельно, надо только помнить, что в онлайне, в браузерах есть ограничения на потоки: IE7 обычно по умолчанию даёт грузить только 4 файла одновременно, FF - 2. Но файлы всё равно загрузяться все.
/**
* @author Denis Kolyako
*/
package ru.etcs.display {
import flash.display.Loader;
import flash.display.LoaderInfo;
import flash.events.IOErrorEvent;
public class LoaderExtended extends Loader {
private var info:LoaderInfoExtended;
public function LoaderExtended() {
super();
info = new LoaderInfoExtended(oldContentLoaderInfo, this);
}
override public function get contentLoaderInfo():LoaderInfo {
return info;
}
public function get oldContentLoaderInfo():LoaderInfo {
return super.contentLoaderInfo;
}
}
}
/**
* @author Denis Kolyako
*/
package ru.etcs.display {
import flash.display.DisplayObject;
import flash.display.Loader;
import flash.display.LoaderInfo;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.IOErrorEvent;
import flash.errors.IOError;
import ru.etcs.events.IOErrorEventExtended;
public class LoaderInfoExtended extends LoaderInfo {
public var name:String;
private var __loader:Loader;
private var __info:LoaderInfo;
private var __dispatcher:EventDispatcher;
public function LoaderInfoExtended(loaderInfo:LoaderInfo, loader:LoaderExtended) {
super();
__loader = loader;
__info = loaderInfo;
__dispatcher = new EventDispatcher();
loaderInfo.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
}
private function ioErrorHandler(event:IOErrorEvent):void {
var evt:IOErrorEventExtended = new IOErrorEventExtended(event.type, event.bubbles, event.cancelable, event.text, this);
__dispatcher.dispatchEvent(evt);
}
override public function addEventListener(type:String, listener:Function, useCapture:Boolean=false, priority:int=0.0, useWeakReference:Boolean=false):void {
__dispatcher.addEventListener(type, listener, useCapture, priority, useWeakReference);
}
override public function get content():DisplayObject {
return __info.content;
}
override public function get loader():Loader {
return __loader;
}
}
}
/**
* @author Denis Kolyako
*/
package ru.etcs.events {
import flash.events.IOErrorEvent;
import flash.display.LoaderInfo;
public class IOErrorEventExtended extends IOErrorEvent {
private var __target:LoaderInfo;
public function IOErrorEventExtended(type:String, bubbles:Boolean=false, cancelable:Boolean=false, text:String="", tgt:LoaderInfo = null) {
super(type, bubbles, cancelable, text);
__target = tgt;
}
public function get loaderInfo():LoaderInfo {
return __target;
}
}
}
USAGE:
import ru.etcs.display.*;
import ru.etcs.events.*;
var loader:LoaderExtended = new LoaderExtended();
loader.name = 'myName';
var ioErrorHandler:Function = function(event:IOErrorEventExtended):void {
trace(event.loaderInfo.loader.name); // myName
}
loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
loader.load(new URLRequest('non-exist-url'));
Не удалось переписать target у IOErrorEvent — ставишь трейс __target, показывает LoaderInfoExtended, потом return __target, но возвращается ссылка на dispatcher (!!!).
з.Ы. Дописать все обработчики в LoaderInfoExtended предлагается самостоятельно ;-).
Dendroid
02.06.2007, 18:29
Хороший вариант. :) Строго, хоть и громоздко. Хотелось бы, конечно, переписать не get на loaderInfo, а сам loaderInfo, а то глядишь ещё какие-нибудь проблемы вылезут как с __target...
Я бы считал проблему решенной, если бы смог переназначить get target (чтобы не юзать в usage-коде IOErrorEventExtended), он переназначается, но возвращается все равно __dispatcher… Почему — непонятно.
Красивое решение могло бы быть, если кто мне скажет-таки как сделать динамичный ContentLoaderInfo, чтобы идентификатор name можно было давать не только в Loader, но и в ContentLoaderInfo. :)
Полностью согласен =)
Кстати мужики респект за ответы. Проблему решил, самым простым способом.
Извращенный способ с слушателями брать не стал, а вот циклическая проверка внешних лоадеров, с евентами - помогла. Вобщем то и вариант расширения класса, очень "гуд", но опять же не хотелось заморачиваться......
Еще раз Респект, и спасибо за ответы.
Извращенный способ с слушателями брать не стал,
Угу, не видел ты извращенных способов :D
Работает на vBulletin ® версия 3.7.3. Copyright ©2000-2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Copyright © 1999-2008 Flasher.ru. All rights reserved.