Если уточнить задачу, то нас интересует тот момент, который наступает после присваивания значения атрибуту srcdoc и моментального обращения к свойству contentDocument.
Напомню, что атрибут принимает строку, которая должна являться частью синтаксиса HTML. Это может быть как полная разметка страницы, так и частичный код.
Смысл работы атрибута srcdoc в том, что мы получаем новый Документ для отображения в iframe. То есть строка из srcdoc будет преобразована в объектную модель документа.
Что это означает для нас? Дело в том, что на построение нового Документа нужно затратить некоторое время.
<!DOCTYPE html>
<html lang=«ru»>
<head>
<meta charset=«UTF-8»>
<meta http-equiv=«X-UA-Compatible» content=«IE=edge»>
<meta name=«viewport» content=«width=device-width, initial-scale=1.0»>
<title>Страница с iframe</title>
</head>
<body>
<script>
let myIframe = document.createElement(‘iframe’);
myIframe.srcdoc = `<p>Какой-то текст в предложении. Что-то ещё напишем</p>`;
console.log(myIframe.contentDocument);
</script>
</body>
</html>
Скриншот разметки:

Без встраивания элемента iframe на страницу текущего Документа, новый Документ не будет создаваться. А значит если мы сразу после присвоения строки для атрибута srcdoc попытаемся обратиться к свойству contentDocument, то нас постигнет неудача — мы получим null.

Если мы встроим элемент на страницу в браузере,
<script>
let myIframe = document.createElement(‘iframe’);
myIframe.srcdoc = `<p>Какой-то текст в предложении. Что-то ещё напишем</p>`;
document.body.append(myIframe);
console.log(myIframe.contentDocument);
</script>
то мы получим стандартную заглушку, без нашей разметки:

Как быть в этой ситуации?
Решение
Нам нужно каким то образом дождаться создания нового Документа, чтобы спокойно обращаться к свойству contentDocument.
Информация из справки:
Каждый документ Document имеет флаг прогресса загрузки iframe (iframe load in progress flag) и флаг отключения загрузки iframe (mute iframe load flag). При создании документа Document эти флаги должны быть сняты для этого документа Document.
Чтобы выполнить шаги события загрузки iframe (iframe load event steps), учитывая элемент элемента iframe:
1. Утверждено: вложенный контекст просмотра элемента element не равен null. 2. Пусть дочерний документ childDocument будет активным документом вложенного контекста просмотра элемента element. 3. Если для childDocument установлен флаг отключения загрузки iframe, возврат. 4. Установите флаг прогресса загрузки iframe для childDocument. 5. Запустите событие с именем load в элементе element. 6. Снять флаг прогресса загрузки iframe дочернего документа childDocument.

Из этого следует то, что у нас есть событие load, которое наступит сразу после загрузки нового Документа в содержимом в iframe. Нам останется просто перехватить его при помощи обработчика событий onload:
<script>
let myIframe = document.createElement(‘iframe’);
myIframe.srcdoc = `<p>Какой-то текст в предложении. Что-то ещё напишем</p>`;
document.body.append(myIframe);
// Вешаем обработчик события onload на наш элемент iframe, который лежит в myIframe
myIframe.onload = () => {
// Вывод в консоль
console.log(myIframe.contentDocument);
// Или набор ваших действий с новым Документом
}
</script>
Скриншот из консоли:

В браузере привычное «синхронное программирование» размывается, так как данные не готовы в каждый момент времени. Нельзя просто начать выполнять следующую операцию не дождавшись предыдущей. Поэтому когда мы работаем в браузере, то мы должны научиться мыслить «событийным программированием«, где какие-то действия начинаются только после наступления какого-то события.
В результате между работами функций появляются паузы, которые неизбежно замедляют работу всего сайта или приложения. Но скорости всё равно неподвластны мозгу обычного человека, поэтому для нас этот процесс по-прежнему похож на «мгновенный» (но это не так 🙂 ).
Информационные ссылки
Стандарт HTML — Раздел «4.8.5 The iframe element» — https://html.spec.whatwg.org/#the-iframe-element