Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Последовательное асинхронное выполнение. (https://javascript.ru/forum/misc/63744-posledovatelnoe-asinkhronnoe-vypolnenie.html)

Bepec 26.06.2016 20:00

Последовательное асинхронное выполнение.
 
День добрый всем заглянувшим.
Проблема:
Умею C++, не умею Javascript. И никак мне не удаётся понять, как можно (или с помощью чего) написать скрипт для автоматизации действий в браузере, с ожиданием загрузок страниц, паузами для загрузки данных и отработки скриптов.

Пока на данный момент написал свой велосипед-менеджер в виде setInterval и очереди задач. Но такой код сложен для понимания, написания и фиг разберёшься в случае ошибок.

Собственно я хочу писать примерно так(псевдокод):
waitToLoadPage();
myAction();
waitToText("Some text");
myTextAction();
waitToLoadData("Some filter");
var data = getData();
alert(data);


А пока получается только колбаса из очереди событий.
function waitToLoadPage()
{
	//some code
	insertQueue(myAction);
}
function myAction()
{
	//some code
	insertQueue(waitToText);
}
function waitToText(text)
{
	//some code
	insertQueue(myTextAction);
}
function myTextAction()
{
	//some code
	insertQueue(waitToLoadData);
}
function waitToLoadData(data)
{
	//some code
	insertQueue(getData);
}
function getData()
{
	//some code
	alert(data);
}


И вопрос - как/чем лучше воспользоваться для реализации такого кода? Скорее всего есть готовые компоненты, но в javascript я новичек.

PS собственно решение - написать свой собственный скриптовый движок, но это довольно затратное решение.

laimas 27.06.2016 00:41

waitToLoadPage(); - обрабатываем событие onload, после чего:
myAction(); - чего-то делаем
waitToText("Some text"); - асинхронный запрос сервера для получения "Some text", который обрабатываем после ответа сервера - XMLHttpRequest
myTextAction(); - чего-то делаем
waitToLoadData("Some filter"); - асинхронный запрос сервера для получения "Some filter", который обрабатываем после ответа сервера - XMLHttpRequest
var data = getData();
alert(data);

Bepec 27.06.2016 02:57

Вы меня неправильно поняли. Я не спрашиваю чем достать данные и какие обработчики ставить.
Скрипт уже работает в виде очереди.

Я спрашиваю, можно ли на Javascript написать приведённый мною код и добиться от него последовательного выполнения.

Чтобы после выполнения первой строки управление переходило на вторую.
Чтобы асинхронные операции не приходилось распределять по трём-четырём функциям.

Можно поставить вопрос проще - можно ли добиться того, чтобы скрипт выполнялся асинхронно, при этом сохраняя последовательный вид кода?

PS пока единственным вариантом мне видится написание скриптового движка, в который будет загоняться этот код. Но возможности языков обширны и поэтому я спрашиваю - если ли более удобное и менее ресурсоёмкое решение?

laimas 27.06.2016 06:43

Цитата:

Сообщение от Bepec
можно ли добиться того, чтобы скрипт выполнялся асинхронно, при этом сохраняя последовательный вид кода?


Можно, при этом писать под каждый запрос сервера свой асинхронный запрос не обязательно. Вряд ли ваш последовательность бесконечна, а значит, если каждая myAction(); индивидуальна, то их можно описать под именами связанными с параметром запроса. А каждый асинхронный запрос отличается как раз только значением этого параметра, как "руководство" для сервера и клиента.

Можно и таймер, но если период запросов мал, то лучше запускать следующую myAction(); после завершения предыдущего запроса, который опираясь на параметрах текущего запроса вызовет следующий myAction(); Например:

var f = {
    exe1 : function() {
          requestServer(2)
    },
    exe2 : function() {
          requestServer(3)
    },
    exe3 : function() {
          alert('End')
    }    
}

function requestServer(p) {
    //асинхронный запрос с параметром var=p
    //получили и обработали ответ, запустили функцию f['exe'+p]()
}


Либо иначе, по иным условиям, запускайте свои myAction().

destus 27.06.2016 07:15

Bepec,
Цитата:

Можно поставить вопрос проще - можно ли добиться того, чтобы скрипт выполнялся асинхронно, при этом сохраняя последовательный вид кода?
Да, конечно можно. На фронте я использую генераторы и библиотеку co. Можно также использовать async/await фукции с подключенным Babel`ем. То есть ты пишешь код в синхронном виде, а выполняется он асинхронно.

https://learn.javascript.ru/generato...ный-код

Erolast 27.06.2016 08:10

Цитата:

можно ли добиться того, чтобы скрипт выполнялся асинхронно, при этом сохраняя последовательный вид кода?
Да. Совсем недавно состоялся релиз ES7, в котором появилась конструкция async/await:

main();

async function main() {
    await loadPage();
    await myAction();
    await text("Some text");
    await myTextAction();
    await loadData("Some filter");
    var data = await getData();
    alert(data);
}

async function waitToLoad() {};
async function myAction() {};

async function getData() {
    let request = await fetch("/api/data");
    let data = await request.json();
    
    return data;
}


А если вдруг надо связать код на async/await со старым, то используются обещания:
function interval(ms) { //Если функция возвращает обещание, к ней можно применить await.
    return new Promise((resolve, reject) => {
        setInterval(resolve, ms);
    });
}

await interval(1000);


Собственно, сначала появились обещания, потом генераторы, и только потом, как синтаксический сахар над их связкой, async/await.

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

Для чтения:
https://developer.mozilla.org/ru/doc...bjects/Promise
https://learn.javascript.ru/es-modern-usage

destus 27.06.2016 08:19

Цитата:

Совсем недавно состоялся релиз ES7, в котором появилась конструкция async/await:
ссылочку на пруф можно? Не нахожу этого тут http://www.ecma-international.org/ec...7.0/index.html. Вижу, что await попал в категорию Future Reserved Words.

Bepec 27.06.2016 13:58

laimas - спасибо за ответ, так у меня сейчас и сделано, но это сложно для отслеживания и для изменения порядка команд, или добавления новой необходимо будет в нескольких функциях править цепочку.

destus - спасибо за ответ, похоже это именно то, что мне нужно. Почитаю.

Erolast - спасибо за ответ, почитаю.

Erolast 27.06.2016 16:33

Цитата:

ссылочку на пруф можно? Не нахожу этого тут
А... и правда, не вошел.

Энивей, он уже release candidate - это значит, что фича проработана и теперь ожидает фидбека, так что юзать можно смело.

Цитата:

спасибо за ответ, почитаю.
Я главное-то забыл скинуть - http://www.2ality.com/2016/02/async-functions.html
Собственно, async/await - это то же самое, что использование генераторов совместно с либой co, просто это родная конструкция языка, не надо ничего подключать.


Часовой пояс GMT +3, время: 21:59.