Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

Шаблоны проектирования Ajax. Выпуск 2.


Здравствуйте!

Как и обещал, публикую перевод очередного шаблона проектирования Ajax. Называется он Scheduling, что я перевёл как "Отложенное исполнение", хотя "Запуск по расписанию" тоже неплохо звучит.

Название исчерпывающе описывает содержание статьи - речь в ней действительно идёт о том, как запускать JavaScript в назначенное время.


Оригинал: Scheduling

Отложенное исполнение

Вкратце

Закачки, совершаемые по графику

История

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

Проблема

Как сделать отложенный или периодический запуск программы?

Причины

  • Иногда, необходимо, чтобы программа повторно совершала одно и тоже действие, например, извлекала новые данные из сервера или контролировала состояние программы.
  • Иногда, необходимо чтобы программа совершала действия через определенное время, например, предупреждала пользователя о том, что время ожидания истекло.
  • Сервер не может установить соединение с клиентом, и поэтому сервер не сможет «разбудить» клиента согласно расписанию.

Решение

Используйте таймеры Javascript , чтобы распланировать действия. Механизм таймера Javascript позволяет Вам намечать одноразовое действие или действие, повторяющееся в установленных интервалах. В любом случае, Вы определяете само действие и период времени в миллисекундах. Обратите внимание: Данные концепции представлены в онлайн демоверсии.

Самым элементарным способом управления действием в будущем мог бы быть такой:

sleep(5000);  // Не работает - такой команды не существует
expire();

Однако, это не сработает, потому что Javascript не поддерживает команду sleep(), т.к. вы не можете просто остановить выполнение скрипта (есть некоторые обходные пути, но на самом деле, и они не подойдут). Вместо этого, вы должны отложить исполнение данного скрипта на будущее.

В большинстве случаев используется планирование некоторых одноразовых действий в будущем. Например, требуется, чтобы приложение Интернет-торговли делало цену устаревшей через 5 секунд:

   ***
   setTimeout(expire, 5000);
   ***
   function expire() { $("price").innerHTML = "Expired"; }

А что, если что-то случится, и Вы захотите отменить таймер? Например, пользователь начал заполнять формуляр, и работу приложения интернет-торговли нужно приостановить, чтобы дать пользователю больше времени. setTimeout вобще говоря возвращает объект таймера, и это позволяет отменить действие.

В данном случае, действие целесообразней было бы отложить, нежели полностью отменить. Этого можно добиться, создавая новый таймер:

До этого момента наше отложенное действие было вызов простой функции expire() Иногда, удобнее написать действия в самом таймере, в этом случае вы сможете уместить всё в одной строке. Это избавит от необходимости создавать специальную функцию для вызова её по таймеру. Строка будет вычислена в момент вызова по таймеру.

setTimeout("'$('price').innerHTML = 'Expired'", 5000); // Избавились от функции.

Работа со строкой также используется, если вам нужно задать аргумент, постоянный или зависящий от некоторой переменной.

Стандартная идиома предусматривает использование замыкания для больших по размеру функций, однако это вызывает ряд замечаний, о которых будет сказано ниже:

Это сработает, но будьте внимательны: name это указатель – он примет значение name, не в момент создания, а когда истечёт заданное в таймере время. Конкретнее, в скрипте ниже вызываются два alert . Как Вы думаете, что они покажут?

Если вы запустите этот скрипт, вы увидете два предупреждения:

Что происходит? В первом случае, name помещается в новый объект строки при создании таймера, и эта же строка будет использоваться, когда таймер истечет. Напротив, второй случай связан с переменной. name, будучи обычной переменной Javascript, указывает на определенный адрес ячейки памяти. Значение в ячейке памяти появится только тогда, когда истечёт заданное в таймере время.

Как, тогда, передавать параметры заданной в таймере функции? Самый легкий способ - создать строку - описан ранее. Другой прием, основан на замыкании и показан здесь (основан на [1])

Механизм повторения - второго типа Отложенного исполнения - практически такой же. Вместо setTimeout, используется setInterval. Опять же, вызов функции возвратит объект таймера, который пригодится, если вы захотите отменить цикл с помощью clearTimeout. Второй параметр - тоже время, но в setInterval, это периодичность. Следующий код будет вызывать refreshData каждые 5 секунд:

setInterval(refreshData, 5000);

Стандартная альтернатива - это задать цикл с помощью setTimeout В этом случае заданная в таймере функция при каждом исполнении повторно задаёт отложенное исполнение самой себя, обычно по какому-нибудь условию. Таким образом, функция будет повторяться, пока выполняется это условие.

Примеры из реальной жизни

Портал Claude Hussenet

Этот портал показывает множество новостей и для их обновления использует таймер, как это описано в Переодическом обновлении.

Google Suggest

Google Suggest предлагает варианты ввода подгружаемые с сервера пока вы вводите запрос. Вместо того чтобы посылать сведения о вводимом запросе при каждом вводе символа, он использует таймер, чтобы указать сколько запросов нужно посылать в секунду. Этот шаблон описан в Submission Throttling.

Apple ITunes Counter

Т.к. на сайте Интернет-магазина ITunes Music Store скачено около 500 миллионов песен, компания Apple разместила на своей домашней странице счетчик, который показывает число загрузок в режиме реального времени. На самом деле это шаблон "Guesstimate(Предположительная оценка)". Каждые несколько минут он получает с сервера данные о продажах, и подчитывает, сколько песен продано в секунду. Между тем, для постоянного обновления счетчика, используется таймер, связанный с общим количеством продаж.

Backpack

Backpack содержит списки с товарами. Когда данные изменяются, то используется визуальный эффект, который называют "Yellow Fade Technique(Техника жёлтого исчезовения)", когда текст ярко загорается, а затем гаснет. Как и большинство визуальных эффектов (One-Second Spotlight, One-Second Mutation, One-Second Motion) этот тоже полагается на таймеры для координации изменения во времени.

Примеры кода

Basic Wiki Demo

Basic Wiki Demo задействует периодическое обновление (Periodic Refresh) каждые пять секунд для синхронизации с сервером. Функция старта и остановки цикла инкапсулирована в своих собственных функциях, для того, чтобы скрыть детали реализации таймера перезагрузки кода.

Как они используются? После загрузки, выполняется начальная синхронизация, и startPeriodicSync () вызывает последующую синхронизацию. Когда пользователь начинает писать в строке сообщения, вызывается stopPeriodicSync, и цикл начинается заново только тогда , когда курсор покидает поле сообщения.

Альтернативы

HTTP Meta Refresh

Тэг HTTP Meta Refresh заставляет браузер загрузить страницу через указанное время. Он используется для удобства новостными порталами, чтобы, например, обновлять содержимое каждые 15 минут. Однако, его употребление ограничено, так как он не воспринимает ввод с браузера и заставляет полностью перезагрузить страницу, при этом не сохраняется текущее состояние запущенных JavaScript-приложений.

Визуальная метафора

Будильник звонит в указанное время. Усовершенствованный будильник также имеет возможность задать повторяющиеся звонки, чтобы будить своих владельцев в одно и то же время каждый день.

Хотите знать больше?

Scott Isaacs о замыканиях и setTimeout

Надеюсь, эта глава поднимет ваши знания Ajax на новый уровень, недоступный конкурентам. Следующий выпуск тоже, скорее всего будет посвящён JavaScript и шаблонам проектирования Ajax, а именно технологии On-Demand Javascript(Javascript по запросу) - тому как подгружать не все сразу библиотеки JavaScript, а лишь по мере необходимости.

На сим остаюсь с вами

Додонов Александр


В избранное