В продолжение
поста про
конечные автоматы в яваскрипт.
Поскольку мне
не подошла готовая библиотека, реализующая
подход FSM, я решил делать свой вариант
реализации. Простой, ничего лишнего,
без блекджека-и-шлюх. В моем варианте
реакция на событие определяется
однозначно через текущее состояние и
само событие. Фактически, строка
«currentState_eventName» дает ссылку на функцию
для исполнения.
Законченный
пример (без HTML кода):
$(document).ready(onDocReady()); function onDocReady() { try { $(document).stopTime('doWork'); $(document).everyTime(999, 'doWork', onTimerWork); } catch(ex) { console.log('Error in function onDocReady: ' + ex.description, true); } } // function onDocReady() function onTimerWork(i) { // work cycle try { // app ready? if (VSClient.isBusy) return; if (VSClient.currentState == '') { VSClient.configure(); return; } VSClient.procEvent('timer'); } catch(ex) { $(document).stopTime('doWork'); VSClient.procEvent('error'); log('Error in function onTimerWork: ' + ex.description, true); } } // function onTimerWork(i) function onSelectFile() { // onClick button 'SelectFile...' try { VSClient.procEvent('selectFile'); } catch (ex) { log('Error in function onSelectFile: ' + ex.description, true); VSClient.procEvent('error'); } return true; } // function onSelectFile() VSClient = { // Object with app data sl: '' // Silverlight object , isBusy: false , fsmTable: [ { from: '', event: 'configure', to: 'ready', action: 'configure' } , { from: 'ready', event: 'selectFile', to: 'wait4FileName', action: 'selectFile' } , { from: 'wait4FileName', event: 'timer', to: 'haveFileName', action: 'getFileName' } , { from: '*', event: 'error', to: 'error', action: 'stopOnError' } ] , currentState: '' , fsmArray: {} , configure: function() { // on page loaded, init app data log('VSClient.configure'); this.isBusy = false; this.sl = $('#silverlightObject')[0].content.vcuSL; this.currentState = 'ready'; for(var n = 0; n < this.fsmTable.length; n++) { var itm = this.fsmTable[n]; this.fsmArray[itm.from + '_' + itm.event] = itm; } try { var res = this.sl.procMessage('test', ''); } catch (ex) { this.sl = ''; this.currentState = ''; } log('VSClient curr.state: ' + this.currentState); } // configure: function(){} }; // VSClient VSClient.procEvent = function(evt) { var llog = log; if (evt == 'timer') llog = function(){;} var ind = this.currentState + '_' + evt; var itm = this.fsmArray[ind] || this.fsmArray['*_' + evt] || ''; if (itm == '') { llog('VSClient.procEvent, no such transition: ' + ind); return; } llog('VSClient.procEvent, tableIndex: ' + ind); this.currentState = itm.to; llog('VSClient curr.state: ' + this.currentState); if (itm.action == '') {} else { this[itm.action].call(this); } } // VSClient.procEvent = function(evt) // { from: 'ready', event: 'selectFile', to: 'wait4FileName', action: this.selectFile } VSClient.selectFile = function() { // fsm action log('VSClient.selectFile'); var res = this.sl.procMessage('selectFile', ''); if(res == '' || res.indexOf('fail') == 0) { // error log('VSClient.selectFile, error: ' + res, true); } else { // wait for SL, user must pick the file $('#inpFileName').val(''); } } // VSClient.selectFile = function() // { from: 'wait4FileName', event: 'timer', to: 'haveFileName', action: this.getFileName } VSClient.getFileName = function() { // fsm action // check if user pick the file var res = VSClient.sl.procMessage('selectFile', 'getName'); if(res == '') { // file not selected this.currentState = 'wait4FileName'; return; } log('VSClient.getFileName, res: [' + res + ']'); log('VSClient curr.state: ' + this.currentState); $('#inpFileName').val(res); } // VSClient.getFileName = function() // { from: '*', event: 'error', to: 'error', action: this.stopOnError } VSClient.stopOnError = function() { // fsm action log('VSClient.stopOnError'); } // VSClient.stopOnError = function() |
По сравнению
с тем, что было (нагромождение if-else), как
небо и земля. Теперь код понятнее изрядно.
Вообще, это я
все терзаю задачу «resumable
http chunked file upload». Просто эталонная
задача для прокачки скиллов. Вот, к
примеру, на хабре попалось:
Если вы
когда-либо загружали видеофайл на сайт,
то знаете это чувство когда загрузилось
90% и вы случайно обновляете страницу.
В этом учебном
руководстве я покажу, как сделать видео
загрузчик для сайта, который может
возобновить прерванную загрузку, и
генерировать обложку после завершения.
...
Чтобы сделать
этот загрузчик, сервер должен отслеживать
процесс загрузки, что бы была возможность
восстановить его при обрыве. Чтобы
выполнить эту задачу... с помощью
Node.js...
мы будем
использовать Socket.io...
Это перевод
вот этой статьи.
Ужасный перевод, но суть уловить можно.
Как совершенно верно заметили в каментах:
Стрёмный
перевод.
Но есть два
полезных момента в статье: из неё вы
узнаете, что Socket.io (посредством WebSocket)
умеет передавать двоичные данные, и что
файл на клиенте можно разбивать на куски
с помощью slice api.
Пойду, попробую
решить задачу возобновляемой отгрузки
файлов на связке HTML5 FileAPI + Node.js + Socket.io
Надо же
проверить, где грабли лежат. А вдруг
многогигабайтные файлы невозможно
обработать? Или — а нахрена тут Node.js,
что, без него нельзя?
Комментариев нет:
Отправить комментарий