Skip to content

Instantly share code, notes, and snippets.

@SelStrom
Last active June 19, 2017 10:34
Show Gist options
  • Save SelStrom/9b3a3a713a40bbf411c38dc6ac16cbef to your computer and use it in GitHub Desktop.
Save SelStrom/9b3a3a713a40bbf411c38dc6ac16cbef to your computer and use it in GitHub Desktop.
package
{
import flash.utils.Dictionary;
/**
* Управление вызовом асинхронных функйии.
* Позволяет выполнять функции последовательно, паралельно и в режиме водопада.
* @author Andrey Shatalov
*/
public class ControllFlow
{
//{ region ------------------------ Public metods
/**
* Позволяет вызвать серию асинхронных методов
* @param metods массив функций, принимают callBack:Function
* @param callBack результаты выполенения методов или обработчик ошибки, принимаеет (error:Object, data:Array)
*/
static public function Series(methods:Array, callBack:Function):void
{
if (methods.length != 0)
{
var task:Function = methods.shift();
task(MapSeries(methods, callBack, []));
}
else
{
callBack(null, null);
}
}
/**
* Паралельный вызов асинхронных методов.
* @param methods массив методов, которые необходимо выполнить паралельно, принимают callBack:Function
* @param callBack результаты выполенения методов или обработчик ошибки, принимаеет (error:Object, data:Array)
*/
static public function Parallel(methods:Array, callBack:Function):void
{
if (methods.length != 0)
{
var taskMap:Array = new Array;
for each (var method:Function in methods)
{
taskMap.push({ task:method, data:null });
}
//вторым циклом запускаем все таски
for (var i:String in taskMap)
{
taskMap[i]['task'](MapParallel(taskMap,callBack,i));
}
}
else
{
callBack(null,null);
}
}
/**
* Последовательный вызов асинхронных методов, которые могут передавать результаты друг другу
* @param methods массив методов, которые выполняются последовательно, принимают ...params,callBack:Function
* @param callBack результаты выполенения методов или обработчик ошибки, принимаеет (error:Object, data:Array)
*/
static public function WaterFall(methods:Array, callBack:Function):void
{
if (methods.length != 0)
{
var task:Function = methods.shift();
task(MapWaterFall(methods, callBack));
}
else
{
callBack(null, null);
}
}
//} endregion --------------------- Public metods
//{ region ------------------------ Private metods
/**
* Конструктор функции, которая будет вызвана колбэком после выполнения метода из списка
* @param methods
* @param callBack
* @param data
* @return
*/
static private function MapSeries(methods:Array, callBack:Function, data:Array ):Function
{
var resp:Function = function(error:Object, newData:*):void
{
if (error == null)
{
if(newData != null) data.push(newData);
if (methods.length != 0)
{
var task:Function = methods.shift();
task(MapSeries(methods, callBack, data));
}
else
{
callBack(null, data);
}
}
else
{
callBack(error, null);
}
}
return resp;
}
/**
* Конструктор, который собирает последовательную обработку асинхронных методов, с возможностью передавать данные в друг друга
* @param methods список методов, которые необходимо выполнить
* @param callBack
* @param ... data произвольное количество параметров
*/
static private function MapWaterFall(methods:Array, callBack:Function):Function
{
var resp:Function = function(error:Object, ... values):void
{
if (error == null)
{
if (methods.length != 0)
{
var task:Function = methods.shift();
//task(MapWaterFall.apply(this,values));//apply позволяет передать заведомо неизвестное количество аргуметов в функцию MapWaterFall
values.push(MapWaterFall(methods,callBack));//добавляем callback в конец массива данных
task.apply(this, values);
}
else
{
callBack(null, values);
}
}
else
{
callBack(error, null);
}
}
return resp;
}
/**
* Конструктор функции для паралельного выполения асинхронных функций
* @param taskMap карта методов вида {task:Function,data:* = null}
* @param callBack
* @param i итератор для taskMap
*/
static private function MapParallel(taskMap:Array, callBack:Function, i:String):Function
{
var foo:Function = function(error:Object, data:* = null):void
{
//Debug.trace(_TITLE_CLASS + 'OnComplete вызван ' + data, Debug.LEVEL_DEBUG);
if (error == null)
{
//Debug.trace(i);
taskMap[i]['data'] = data? data: { complete: true };//NOTE на будущее стоит пересмотреть данные по умолчанию
for each (var item:Object in taskMap)
{
if (item['data'] == null) return;
}
//код ниже выполнится, если карта задач окажется заполена данными, которые != null
//по идее будет выполнена только один раз
var respData:Array = new Array();
for each (item in taskMap)
{
respData.push(item['data']);
}
callBack(null, respData);
}
else
{
callBack(error, null);//NOTE в случае ошибок колбек будет вызван для каждой
}
}
return foo;
}
//} endregion --------------------- Private metods
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment