# Догрузка страницы

> Поле settled: получили вы всё или обрывок — и как отличить одно от другого

Источник: https://docs.parreq.com/browser-settled/

После каждого шага — и после `open`, и после `click`, и после `fill` — сервис
ждёт, пока страница догрузится. Итог ожидания приходит в поле `settled`.

## Почему тишины в сети мало

Обычная проверка «сеть замолчала — значит готово» здесь не работает. Скрипт
может дорисовывать уже загруженное, ничего при этом не запрашивая, и снаружи это
неотличимо от готовой страницы: запросов нет, а содержимое ещё меняется.

Поэтому смотрим три вещи разом:

**Состояние документа**
    Разобрана ли разметка — `readyState` дошёл до `interactive`.

**Сетевые записи**
    Прекратились ли запросы страницы.

**Изменения DOM**
    Перестало ли меняться дерево узлов.

Готовым считается то, что успокоилось по всем трём.

> **Примечание.**
>   Достаточно `interactive`, а не `complete`, и это важно. `complete` наступает
>   после события `load`, то есть после последнего подресурса — счётчика, пикселя,
>   шрифта со стороннего домена. Одного недоступного хватает, чтобы `load` не
>   наступил никогда, а разметка при этом разобрана давно и кнопки на месте.
>   Ждать в такой ситуации нечего.

## Ранний выход по цели

Если в `include` заказаны `buttons` или `fields`, ожидание следит ещё и за тем,
сколько таких элементов на странице. Как только они найдены и их число не
меняется, ожидание кончается — не дожидаясь общей тишины.

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

В таком случае в `reason` стоит «нужные элементы собраны», а `settled` всё равно
`true`: вы получили то, за чем шли.

## Что приходит

```json
{"settled": true,  "reason": "страница догрузилась: 428 узлов, 12 сетевых записей, 61 изменение DOM",
 "ms": 940, "ready": "complete", "mut": 61, "res": 12, "nodes": 428, "goal": 37}
{"settled": true,  "reason": "нужные элементы собраны: 43 шт., 1580 узлов; страница ещё меняется",
 "ms": 1053, "ready": "interactive", "mut": 210, "res": 64, "nodes": 1580, "goal": 43}
{"settled": false, "reason": "остановлено по времени (15000 мс), страница продолжала меняться",
 "ms": 15079, "ready": "loading", "mut": 4, "res": 28, "nodes": 12, "goal": 0}
```

- **`settled`** (`boolean`):
  `true` — дождались; `false` — вышло время, а страница ещё менялась.

- **`reason`** (`string`):
  Чем кончилось ожидание, человеческими словами: сколько узлов, сетевых записей
  и изменений насчитано, либо по какому сроку остановились.

- **`ms`** (`integer`):
  Сколько миллисекунд ждали.

- **`ready`** (`string`):
  Состояние документа на момент выхода: `loading`, `interactive` или `complete`.
  Первое означает, что разметка ещё разбиралась, — тогда список элементов пуст
  не потому, что их нет, а потому, что их ещё не разобрали.

- **`nodes`** (`integer`):
  Сколько узлов в документе. Полтора десятка — страница пустая; сотни и
  тысячи — разобранная.

- **`goal`** (`integer`):
  Сколько заказанных элементов (кнопок и полей) насчитано в последнем опросе.
  `-1` — цель не заказана: в `include` нет ни `buttons`, ни `fields`.

- **`mut`** (`integer`):
  Изменений DOM за время ожидания.

- **`res`** (`integer`):
  Сетевых записей страницы.

## Как читать `settled: false`

Разница важна: в первом случае вы получили всё, во втором — обрывок, и **знаете
об этом**. Список элементов в обрывке может быть неполным: кнопка, которую
дорисовывает скрипт, ещё не появилась.

> **Примечание.**
>   Есть страницы, которые не успокаиваются никогда: бегущие строки, часы,
>   анимация, ленты с автообновлением. Для них `settled: false` — норма, а не
>   поломка. Проверьте по `elements`: если нужный элемент на месте, работайте
>   дальше.

Разумная реакция:

```python
res = click(session, ref)
if not res["settled"]["settled"] and not find_ref(res["elements"], "Оплатить"):
    # страница ещё рисуется и нужного элемента нет — дайте ей шаг форы
    res = click(session, harmless_ref)
```

Отдельной ручки «подожди ещё» нет: любой шаг сам по себе ждёт догрузки, поэтому
дешевле сделать следующее действие, чем ждать вхолостую.

## Связанные страницы

**[Элементы и ссылки](https://docs.parreq.com/browser-elements)**
    Что делать, если элемент из списка исчез.

**[Ошибки](https://docs.parreq.com/browser-errors)**
    Когда `settled: false` переходит в отказ `page_error`.
