Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #71 (permalink)  
Старый 25.12.2011, 09:17
Аватар для x-yuri
Отправить личное сообщение для x-yuri Посмотреть профиль Найти все сообщения от x-yuri
 
Регистрация: 27.12.2008
Сообщений: 4,201

я говорил о data как об аргументе для перехода от функции к объекту. Потому что этот data будет странно смотреться в твоей реализации.

Сообщение от FINoM
Что ты имеешь в виду? data — это функция и, по совместительству, — объект.
по сути, у тебя функция, потому что вызывается так:
wait(function() {...})...

а у меня объект, потому что вызывается так:
new AsyncChain(...).add(function() {...})...
Ответить с цитированием
  #72 (permalink)  
Старый 25.12.2011, 20:15
Аватар для FINoM
Новичок
Отправить личное сообщение для FINoM Посмотреть профиль Найти все сообщения от FINoM
 
Регистрация: 05.09.2010
Сообщений: 2,298

x-yuri, я тебя не понимаю.
Сообщение от x-yuri
по сути, у тебя функция, потому что вызывается так:
Сообщение от x-yuri
а у меня объект, потому что вызывается так:
Причем здесь это? Ты хотел передавать некий объект через всю цепочку, не используя аргументов в функции-звене. Я так и сделал.
Ответить с цитированием
  #73 (permalink)  
Старый 26.12.2011, 13:53
Аватар для x-yuri
Отправить личное сообщение для x-yuri Посмотреть профиль Найти все сообщения от x-yuri
 
Регистрация: 27.12.2008
Сообщений: 4,201

нет, я хотел хранить состояние в цепочке. А передача объекта через всю цепочку - это решение в контексте твоего подхода.

И нету смысла делать так, как я сказал. Ты должен сам видеть необходимость. Если не видишь - делай по-своему.

Еще раз, я тебе хотел сказать одну вещь: ты слишком упрощаешь, когда используешь функции, вместо объектов. Все. Необходимость хранить состояние - это всего лишь аргумент в пользу использования объектов.
Ответить с цитированием
  #74 (permalink)  
Старый 26.12.2011, 20:57
Аватар для x-yuri
Отправить личное сообщение для x-yuri Посмотреть профиль Найти все сообщения от x-yuri
 
Регистрация: 27.12.2008
Сообщений: 4,201

давайте все же расмотрим конкретный пример: ресайз картинок на клиенте с помощью flash.

Например, есть форма изменения юзерпика, в которой пользователь выбирает изображение. В результате появляется диалоговое окно, в котором пользователь указывает, как надо обрезать это изображение. Нажимает "Ok" диалогового окна, потом кнопку "Сохранить" формы. Получается что-то типа:
var chain = new AsyncChain();
$('jsChangeUserpicForm-eUserpicField').addEvent('change',   // input type="file"
    chain
        .setOptions({
            onFailure: function() {
                // показать пользователю сообщение об ошибке
                this.fireEvent('complete');
            },
            onComplete: function() {
                new Button('jsChangeUserpicForm-eAttachFileLink')
                    .enable();
                $('jsChangeUserpicForm-eAttachFileThrobber')
                    .addClass('sInvisible');
                this.state('cropResizeUserpicDialog')
                    && this.state('cropResizeUserpicDialog').close();
            }
        })
        .add(function() {
            new Button('jsChangeUserpicForm-eAttachFileLink')
                .disable();
            $('jsChangeUserpicForm-eAttachFileThrobber')
                .removeClass('sInvisible');
        })
        .add(function(NEXT) {
            sendForm({
                form: 'jsChangeUserpicForm',
                url: '/upload/userpic',
                onSuccess: function(userpicURL) {
                    chain.state('userpicURL', userpicURL);
                    NEXT();
                },
                onFailure: function() {
                    chain.fireEvent('failure');
                }
            });
        })
        .add(function(NEXT) {
            this.state('cropResizeUserpicDialog', new CropResizeUserpicDialog({
                userpicURL: chain.state('userpicURL'),
                dstWidth: 100,
                dstHeight: 100,
                onOk: function(cropX, cropY, cropWidth, cropHeight, resizeWidth, 

resizeHeight) {
                    this.state({
                        cropX: cropX,
                        cropY: cropY,
                        cropWidth: cropWidth,
                        cropHeight: cropHeight,
                        resizeWidth: resizeWidth,
                        resizeHeight: resizeHeight
                    });
                    NEXT();
                },
                onCancel: function() {
                    chain.fireEvent('complete');
                }
            }));
        })
        .add(function() {
            this.state('cropResize', new CropResize());
            this.state('cropResize').load(this.state('userpicURL'), {
                onSuccess: function() {
                    NEXT();
                },
                onFailure: function() {
                    chain.fireEvent('failure');
                }
            });
        })
        .add(function() {
            this.state('cropResize')
                .crop(
                    this.state('cropX'),
                    this.state('cropY'),
                    this.state('cropWidth'),
                    this.state('cropHeight')
                )
                .resize(
                    this.state('resizeWidth'), this.state('resizeHeight'),
                )
                .save({
                    url: '/upload/thumb',
                    onSuccess: function() {
                        NEXT();
                    },
                    onFailure: function() {
                        chain.fireEvent('failure');
                    }
                });
        })
        .add(function() {
            if ($('jsChangeUserpicForm-eUserpicURLField')) {
                var eUserpicURLField = $('jsChangeUserpicForm-eUserpicURLField');
            } else {
                var eUserpicURLField = new Element({
                    id: 'jsChangeUserpicForm-eUserpicField',
                    type: 'hidden'
                });
                eUserpicURLField.inject('jsChangeUserpicForm');
            }
            eUserpicURLField.name = 'userpic-url';
            eUserpicURLField.value = this.state('userpicURL');

            $('jsChangeUserpicForm-eUserpicThumb').src = this.state('userpicURL');
        });
);

дополнительные преимущества:
1) возможность научить addEvent запускать цепочки в ответ на событие;
2) предоставление интерфейса для работы с состоянием позволяет повторно использовать цепочку - для этого надо перед запуском цепочки очистить состояние; если пользователь сам придумывает, где хранить состояние, нету возможности его очистить;
3) возможность организовать аналогию блока finally из try-catch (событие complete).

p.s. это я называю конкретным примером. Наличие кода необязательно в общем-то, но в твоем примере с гипотетическим парсером непонятно даже какие действия составляют цепочку, не говоря уже о данных, составляющих состояние цепочки. Т.е. не хватает важной информации.

Последний раз редактировалось x-yuri, 26.12.2011 в 21:03.
Ответить с цитированием
  #75 (permalink)  
Старый 27.12.2011, 00:04
Аватар для x-yuri
Отправить личное сообщение для x-yuri Посмотреть профиль Найти все сообщения от x-yuri
 
Регистрация: 27.12.2008
Сообщений: 4,201

Сообщение от FINoM
Пытаюсь разобраться в backbonejs, смотрю примеры, понимаю как они работают, но не понимаю главного: зачем они так работают и как строить хваленные масштабные приложения с помощью сабжа. Может есть какие-нибудь статьи или книга "для чайников"?
попробовал привлечь DjDiablo к этому вопросу в этой теме
Ответить с цитированием
  #76 (permalink)  
Старый 27.12.2011, 01:39
Аватар для FINoM
Новичок
Отправить личное сообщение для FINoM Посмотреть профиль Найти все сообщения от FINoM
 
Регистрация: 05.09.2010
Сообщений: 2,298

Сообщение от x-yuri
1) возможность научить addEvent запускать цепочки в ответ на событие;
Это круто. Только пока не понимаю, как грамотно и удобно возвращать и вызывать функцию. Наверно, идея гозара с методом, запускающим цепочку пойдет.
Сообщение от x-yuri
onFailure
Тоже круто, только
Сообщение от x-yuri
// показать пользователю сообщение об ошибке
                this.fireEvent('co mplete');
вот этого я не понял. Не смотря на опечатку (вместо 'complete' наверно должно быть 'failure') чем является this? Это контекст события?

Сообщение от x-yuri
 onComplete:
Зачем оно? Можно ведь в последнюю функцию запихать.
Сообщение от x-yuri
предоставление интерфейса для работы с состоянием позволяет повторно использовать цепочку - для этого надо перед запуском цепочки очистить состояние; если пользователь сам придумывает, где хранить состояние, нету возможности его очистить;
Ну только сейчас догнал, где оно может примениться.
Сообщение от x-yuri
непонятно даже какие действия составляют цепочку
Как же не понятно? Там ведь простые функции.
Сообщение от x-yuri
не говоря уже о данных, составляющих состояние цепочки
В примере состояния просто-напросто не нужны. Функции выполняются строго по-порядку, используя какую-то переменную из предыдущего вызова, если таковая есть. Того, что я предложил в начале достаточно для 90% задач, использующих асинхронные очереди.
Ответить с цитированием
  #77 (permalink)  
Старый 27.12.2011, 16:36
Аватар для x-yuri
Отправить личное сообщение для x-yuri Посмотреть профиль Найти все сообщения от x-yuri
 
Регистрация: 27.12.2008
Сообщений: 4,201

Сообщение от FINoM
Это круто. Только пока не понимаю, как грамотно и удобно возвращать и вызывать функцию. Наверно, идея гозара с методом, запускающим цепочку пойдет.
какую функцию? Метод, запускающий цепочку, вызывает addEvent

Сообщение от FINoM
вот этого я не понял. Не смотря на опечатку (вместо 'complete' наверно должно быть 'failure') чем является this? Это контекст события?
там должно быть именно complete. Цепочка не знает, когда должны происходить эти события. Это задача использующего кода. Это же событие запускается если пользователь передумал, нажал "Отмена" в диалоге. this обычно указывает на объект-источник события, в частности в данном случае.

Сообщение от FINoM
Зачем оно? Можно ведь в последнюю функцию запихать.
и как ты отмену собираешься обрабатывать? Напиши свою версию этого кода

Сообщение от FINoM
Ну только сейчас догнал, где оно может примениться.
я это применение придумал, когда писал этот пример. Добавление состояния ничего не усложняет, и как видим ему нашлось применение.

Сообщение от FINoM
Как же не понятно? Там ведь простые функции.
Простые ничего полезного не делающие, ничего не обозначающие функции. У тебя абстрактный пример.

Сообщение от FINoM
В примере состояния просто-напросто не нужны. Функции выполняются строго по-порядку, используя какую-то переменную из предыдущего вызова, если таковая есть. Того, что я предложил в начале достаточно для 90% задач, использующих асинхронные очереди.
Что нужно в примере непонятно. Он может показать, как пользоваться твоей функцией. Но по нему нельзя сказать, достаточно ли функционала у твоей функции. Задача либо абстрактная, либо недостаточно подробно описана.

Сообщение от FINoM
Того, что я предложил в начале достаточно для 90% задач, использующих асинхронные очереди.
ну раз ты так говоришь, тогда я действительно зря усложняю А что ты будешь делать, когда ты столкнешься с этими 10% задач? Будешь добавлять костыли к своему решению? Или перепишешь его со всем использующим кодом?
Ответить с цитированием
  #78 (permalink)  
Старый 27.12.2011, 17:15
Аватар для FINoM
Новичок
Отправить личное сообщение для FINoM Посмотреть профиль Найти все сообщения от FINoM
 
Регистрация: 05.09.2010
Сообщений: 2,298

Сообщение от x-yuri
какую функцию? Метод, запускающий цепочку, вызывает addEvent
Обычный запуск цепочки:
chain.add(...).add(...).run()
Запуск по событию:
doc.addEventListener(event, chain.add(...).add(...).run);
В первом случае мы сами вызываем функцию, во втором, передаем функцию для запуска после отлова события.
Сообщение от x-yuri
this обычно указывает на объект-источник события, в частности в данном случае.
Не понял фразы.
Сообщение от x-yuri
и как ты отмену собираешься обрабатывать? Напиши свою версию этого кода
Вместо
chain.setOptions({
   onComplete: function(){blabla()}
}).add(function first(){}).add(function second(){})

писать
chain.add(function first(){}).add(function second(){}).add(function() blabla()})

Сообщение от x-yuri
я это применение придумал, когда писал этот пример. Добавление состояния ничего не усложняет, и как видим ему нашлось применение.
А где хранить состояние? В замкнутом объекте? В смысле, чтоб пользователь не имел к нему доступа напрямую.
Сообщение от x-yuri
Простые ничего полезного не делающие, ничего не обозначающие функции. У тебя абстрактный пример.
Блин, чем тебе пример не нравится. Или ты предлагаешь заменить функции на существующие? Какая разница, если суть от этого не изменится? Давай так: ты работал с нодой?
Сообщение от x-yuri
Что нужно в примере непонятно. Он может показать, как пользоваться твоей функцией. Но по нему нельзя сказать, достаточно ли функционала у твоей функции. Задача либо абстрактная, либо недостаточно подробно описана.
То же самое. Задача описана для тех, кто знает, что такое серверный асинхронный JS.
Сообщение от x-yuri
А что ты будешь делать, когда ты столкнешься с этими 10% задач? Будешь добавлять костыли к своему решению? Или перепишешь его со всем использующим кодом?
Нет. Буду пользоваться тем, что есть. По крайней мере, в твоем примере, я не увидел того, что не решалось бы моим способом.
Ответить с цитированием
  #79 (permalink)  
Старый 27.12.2011, 19:07
Аватар для x-yuri
Отправить личное сообщение для x-yuri Посмотреть профиль Найти все сообщения от x-yuri
 
Регистрация: 27.12.2008
Сообщений: 4,201

Сообщение от FINoM
Обычный запуск цепочки:
chain.add(...).add(...).run()
Запуск по событию:
doc.addEventListener(event, chain.add(...).add(...).run);
В первом случае мы сами вызываем функцию, во втором, передаем функцию для запуска после отлова события.
зачем, если можно научить addEvent работе с цепочками? Передаем ей цепочку, а она сама вызывает run.

Сообщение от x-yuri
this обычно указывает на объект-источник события, в частности в данном случае.
Сообщение от FINoM
Не понял фразы.
что в js, что в mootools, this в обработчике указывает на объект, который сгенерировал событие. Моя реализация следует этому соглашению. И jquery тоже.

Сообщение от FINoM
Вместо
chain.setOptions({
onComplete: function(){blabla()}
}).add(function first(){}).add(function second(){})

писать
chain.add(function first(){}).add(function second(){}).add(function() blabla()})
да, удобнее приводить такие вот схематические примеры, которые скрывают недостатки. Должно было быть так:
chain.setOptions({
    onComplete: function() {
        // выполняем завершающие действия
    }
}).add(function() {
    this.fireEvent('complete');
}).add(function() {
    // делаем что-то еще
}).add(function() {
    // делаем что-то еще
});

chain
    .add(function() {
        runNext(true);
    })
    .add(function(ignore) {
        if ( ! ignore) {
            // делаем что-то еще
        }
        runNext(ignore);
    })
    .add(function(ignore) {
        if ( ! ignore) {
            // делаем что-то еще
        }
        runNext(ignore);
    })
    .add(function(ignore) {
        if (ignore) {
            // выполняем завершающие действия
        }
    });


Сообщение от FINoM
А где хранить состояние? В замкнутом объекте? В смысле, чтоб пользователь не имел к нему доступа напрямую.
если пользователь что-то делает напрямую, либо он знает, что делает, либо ССЗБ

Сообщение от FINoM
Блин, чем тебе пример не нравится. Или ты предлагаешь заменить функции на существующие? Какая разница, если суть от этого не изменится? Давай так: ты работал с нодой?
посмотри на пример выше и сравни со своим. У тебя не видно, что твой подход приводит к куче ненужного кода. С нодой работал, но не сильно. Собственно, и что? У нас тут в теме пользователь ноды, который вообще не видит проблемы. Приведи хотя бы какой-нибудь реальный пример, в котором видно, какие выполняются действия и какие передаются данные, а лучше самый сложный, если ты не хочешь ничего скрывать.

Сообщение от FINoM
То же самое. Задача описана для тех, кто знает, что такое серверный асинхронный JS.
задача не описана, описана проблема. По проблеме нельзя судить о том, достаточно функциональности у твоей функции или нет.

Сообщение от FINoM
Нет. Буду пользоваться тем, что есть. По крайней мере, в твоем примере, я не увидел того, что не решалось бы моим способом.
хорошо, давай посмотрим на то, что есть и на то, что будет:
$('userpic').addEvent('change',   // input type="file"
    function() {
        chain
            .add(function(runNext) {
                $('attach-file').addClass('disabled');
                $('attach-file-throbber')
                    .removeClass('invisible');

                sendForm({
                    form: 'change-userpic-form',
                    url: '/upload/userpic',
                    onSuccess: function(userpicURL) {
                        runNext(false, userpicURL);
                    },
                    onFailure: function() {
                        runNext(true);
                    }
                });
            })
            .add(function(runNext, failure, userpicURL) {
                if (failure) {
                    runNext(true);
                }
                var cropResizeUserpicDialog = new CropResizeUserpicDialog({
                    userpicURL: userpicURL,
                    dstWidth: 100,
                    dstHeight: 100,
                    onOk: function(cropX, cropY, cropWidth, cropHeight, resizeWidth, resizeHeight) {
                        runNext(false, false, userpicURL, cropResizeUserpicDialog, cropX, cropY, cropWidth, cropHeight, resizeWidth, resizeHeight);
                    },
                    onCancel: function() {
                        runNext(true);
                    }
                }));
            })
            .add(function(runNext, ignore, failure, userpicURL, cropResizeUserpicDialog, cropX, cropY, cropWidth, cropHeight, resizeWidth, resizeHeight) {
                if (ignore) {
                    runNext(true);
                }
                if (failure) {
                    runNext(false, true);
                }
                var cropResize = new CropResize();
                cropResize.load(userpicURL, {
                    onSuccess: function() {
                        runNext(false, false, userpicURL, cropResizeUserpicDialog, cropX, cropY, cropWidth, cropHeight, resizeWidth, resizeHeight, cropResize);
                    },
                    onFailure: function() {
                        runNext(false, true);
                    }
                });
            })
            .add(function(runNext, ignore, failure, userpicURL, cropResizeUserpicDialog, cropX, cropY, cropWidth, cropHeight, resizeWidth, resizeHeight, cropResize) {
                if (ignore) {
                    runNext(true);
                }
                if (failure) {
                    runNext(false, true);
                }
                cropResize
                    .crop(cropX, cropY, cropWidth, cropHeight)
                    .resize(resizeWidth, resizeHeight)
                    .save({
                        url: '/upload/thumb',
                        onSuccess: function() {
                            runNext(false, false, userpicURL, cropResizeUserpicDialog);
                        },
                        onFailure: function() {
                            runNext(true);
                        }
                    });
            })
            .add(function(failure, userpicURL, cropResizeUserpicDialog) {
                if (failure) {
                    // показать пользователю сообщение об ошибке
                } else {
                    if ($('userpic-url')) {
                        var usrpicUrl = $('userpic-url');
                    } else {
                        var usrpicUrl = new Element({
                            id: 'userpic-url',
                            type: 'hidden'
                        });
                        usrpicUrl.inject('change-userpic-form');
                    }
                    usrpicUrl.name = 'userpic-url';
                    usrpicUrl.value = userpicURL;

                    $('eUserpicThumb').src = userpicURL;
                }

                $('attach-file').removeClass('disabled');
                $('attach-file-throbber')
                    .addClass('invisible');
                cropResizeUserpicDialog
                    && cropResizeUserpicDialog.close();
            });
    }
);


p.s. ты либо специально скрываешь недостатки, либо... не специально. И даже если мое решение требуется в исключительных случаях... чем твое решение лучше существующих для ноды?

Последний раз редактировалось x-yuri, 27.12.2011 в 19:38.
Ответить с цитированием
  #80 (permalink)  
Старый 27.12.2011, 19:49
Аватар для FINoM
Новичок
Отправить личное сообщение для FINoM Посмотреть профиль Найти все сообщения от FINoM
 
Регистрация: 05.09.2010
Сообщений: 2,298

Сообщение от x-yuri
зачем, если можно научить addEvent работе с цепочками? Передаем ей цепочку, а она сама вызывает run.
Ну а если мы хотим вызвать цепочку, то получится так: ...add().add().add()() ← видишь?
Сообщение от x-yuri
this в обработчике указывает на объект, который сгенерировал событие. Моя реализация следует этому соглашению.
Ты же хочешь использовать всякие вещи, типа this.state в функциях. Получается, что в обработчиках (oncomplete, onfailure) this будет элементом из события (в случае прямого запуска это будет window), а в функциях из цепочки this будет являться объектом chain?
Сообщение от x-yuri
Должно было быть так
Кто определяет как должно быть?
Сообщение от x-yuri
Приведи хотя бы какой-нибудь реальный пример, в котором видно, какие выполняются действия и какие передаются даныне.
Блин, привел же.
Сообщение от x-yuri
У нас тут в теме пользователь ноды, который вообще не видит проблемы.
Значит для него вложенные вызовы — это нормально.
Сообщение от x-yuri
задача не описана, описана проблема.
Описана задача сделать этот код более плоским.
Сообщение от x-yuri
чем твое решение лучше существующих для ноды?
Каких именно? Приведи хотя-бы одно.
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Мой сайт. Логические игры. MininAS Ваши сайты и скрипты 45 20.09.2013 23:22
Оцените мой сайт: Большой Русский Форум ФОРУМ Ваши сайты и скрипты 2 16.05.2010 13:27
Мой сайтик маримьяна Ваши сайты и скрипты 4 15.04.2009 14:32
Синхронный запрос данных по AJAX Shasoft AJAX и COMET 2 03.03.2009 14:07