Как исправить код, чтобы тестовый (сейчас неработающий) вывод числа, реализованный для div с id="d1", заработал также для div с id="d2"? <br/> <pre><code class="javascript">/* html:
Нужен небольшой контекст — какой у вас текущий код — но чаще всего проблема в одном из трёх мест:
- Скрипт выполняется до того, как в DOM появились div#d2 (решение: перенести <script> ниже HTML или слушать DOMContentLoaded).
- Вы обращаетесь к коллекции/узлу неправильно (напр., попытка присвоить innerHTML всей NodeList вместо отдельного элемента).
- Функция возвращает Promise (асинхронная) и вы не ждёте результат.
Ниже — несколько корректных вариантов вывода результата функции в оба div.
1) Простой синхронный пример (скрипт после HTML):
HTML:
<div id="d1"></div>
<div id="d2"></div>
JS:
function getNumber() {
return 123;
}
document.getElementById('d1').textContent = getNumber();
document.getElementById('d2').textContent = getNumber();
2) Если скрипт в <head> и элементы ещё не созданы — оберните в DOMContentLoaded:
document.addEventListener('DOMContentLoaded', function () {
document.getElementById('d1').textContent = getNumber();
document.getElementById('d2').textContent = getNumber();
});
3) Если функция асинхронная (возвращает Promise):
async function getNumberAsync() {
return 123;
}
getNumberAsync().then(value => {
document.getElementById('d1').textContent = value;
document.getElementById('d2').textContent = value;
});
или с async/await:
(async () => {
const value = await getNumberAsync();
document.getElementById('d1').textContent = value;
document.getElementById('d2').textContent = value;
})();
4) Если у вас не id, а класс и вы хотите записать в все элементы:
document.querySelectorAll('.myDiv').forEach(el => {
el.textContent = getNumber();
});
5) Частые ошибки и их исправления:
- Не используйте document.querySelectorAll(...).innerHTML — нужно пройтись по NodeList.
- Проверьте, что id уникальны и что d2 действительно существует (console.log(document.getElementById('d2'))).
- Для вставки текста безопаснее textContent, для HTML — innerHTML.
Если пришлёте ваш текущий (неработающий) код — посмотрю и укажу конкретную правку.
Вы не понимаете логику асинхронности в JS. <br/> Когда родительская функция вызывает setTimeout, ядро JS создаёт таймер и привязывает к нему ссылку на функцию и окружение. После этого родительская функция продолжает свою работу. При срабатывании таймера, привязанная к нему функция с окружением помещается в очередь макрозадач и выполняется, когда до неё дойдёт очередь. Как правило, родительская функция к тому моменту давно уже завершилась. <br/> Примерно то же самое выполняется для любой асинхронной функции с тем исключением, что функции-обещания (Promise) помещаются в приоритетную очередь микрозадач. <br/> Ваш код <br/> <pre><code class="javascript">function getNum(){
let a;
setTimeout(function(){a = 5;}, 2000);
return a;
}</code></pre> выполняется как <pre><code>// Вызов getNum()
let a;
setTimeout(fn, 2000); // Здесь создаётся таймер с привязанной функцией и лексическим окружением, сама функция не вызывается
return a;
...
// Сработал таймер, fn помещена в очередь
// Вызов fn
a = 5;</code></pre> <br/> <br/> P.S. Да, в JS фактически один поток выполнения задачи и служебные потоки для таймеров, ввода/вывода и прочих задач ядра. Полноценного параллелизма в нём нет, все функции основного потока выполняются только по очереди.
`setTimeout` не Promise — он возвращает id таймера, поэтому `a` остаётся `undefined` к моменту `return`. <br/> <br/> Оберни в Promise: <br/> <br/> <pre><code>async function loadNum() {
return new Promise(resolve => setTimeout(() => resolve(55), 2000));
}
(async () => {
document.getElementById("d2").innerHTML = await loadNum();
})();</code></pre> <br/> <br/> Или через `.then()`: <pre><code>loadNum().then(n => document.getElementById("d2").innerHTML = n);</code></pre>
Такие упражнения, обычно, предлагают выполнить, чтобы понять боль отсутствия async/await в ранних стандартах языка JS. <br/> Если решать задачу по старинке, то вам нужно тащить ссылку на элемент внутрь callback функции (и остальной контекст некоторых переменных) , чтобы в нужный момент наполнить элемент содержимым: <br/> <pre><code class="javascript">var d2_elem = document.getElementById("d2");
var d2_func = (function(elem, a) {
return function() {
// В этой области мы заморозили замыканием и ссылку на элемент, и значение a.
elem.innerHTML = a;
}
})(d2_elem, 55);
loadNum(d2_func); // ссылка на функцию d2_func содержит в себе замороженные d2_elem и 55, теперь можно эту функцию использовать для отложенного вызова или вызывать по какому-нибудь событию
function loadNum(callback) {
setTimeout(callback, 2000);
}</code></pre>