setTimeout вызывается не синхронно, а после того, как сработало событие «load» вкладки, к этому времени forEach
l oop завершил работу и оставил newTabs.length - 1
со ссылкой на последнюю вкладку.
Одним из решений может быть использование переменной для замены многократного использования length-1
. Не проверено, но в соответствии с:
alert_list.forEach((currentValue, currentIndex) => {
alert_status = currentValue.childNodes[13].innerText;
if(alert_status == "Enabled") {
// console.log(currentValue.childNodes[3].innerText + " " + currentValue.childNodes[7].innerText);
let tabWin = window.open(currentValue.childNodes[5].children[0].href, "_blank")
newTabs.push( tabWin);
tabWin.onload = function(event) {
setTimeout( () => {
window.parent.postMessage(
tabWin.document.querySelectorAll("h1.search-name.section-title.search-title-searchname")
[0].innerText
);
}, 120*1000);
};
}
});
Вот оригинальный код с отступом, чтобы более четко показать, где происходит отложенная оценка (с объявлением, добавленным для alert_status
:
alert_list.forEach((currentValue, currentIndex) => {
let alert_status = currentValue.childNodes[13].innerText;
if(alert_status == "Enabled") {
console.log(currentValue.childNodes[3].innerText + " " + currentValue.childNodes[7].innerText);
newTabs.push(window.open(currentValue.childNodes[5].children[0].href, "_blank"));
newTabs[newTabs.length - 1].onload = function() {
setTimeout(
(
(tab_element) => {
return () => {
window.parent.postMessage(tab_element.document.querySelectorAll("h1.search-name.section-title.search-title-searchname")[0].innerText);
}
}
)(newTabs[newTabs.length - 1])
, 120*1000);
};
}
});
Анонимная функция onload компилируется в функциональный объект, когда она добавляется, но не выполняется до тех пор, пока не сработает событие load.После выполнения она создает «замыкание» для tab_element
, принимая его значение из newTabs[newTabs.length - 1]
, которое является теперь последний элемент табуляции.
Решение состоит в том, чтобы удалить код трюка, который вызывает проблему.
Принцип работы замыканий в JavaScript - это topi c. Однако введение для целей объяснения этого ответа:
Когда вызывается функция, запись (объект в терминах JavaScript) используется для хранения значений переменных и функций используется внутри функции. Фактически, идентификаторы переменных теперь связаны с такой «записью среды». В ES3 и более ранних версиях в блоке не требовалось никаких дополнительных записей level (для операторов в фигурных скобках) или для особого случая for( let identifier...
l oop, поскольку объявления let
, const
и class
еще не введены. Одна запись среды в ES3 была названа «объектом активации».
Обычно, когда функция возвращается, записи среды, созданные для отдельного вызова, могут быть собраны сборщиком мусора на том основании, что они не могли этого сделать. больше должно быть достигнуто через код - текущий критерий для JavaScript сбора мусора в памяти (MG C).
Если и при этом значения вложенных функций и переменных могут если после выхода из функции они будут доступны в коде, они не могут быть удалены из памяти. Эта ситуация обычно описывается как функции и переменные, содержащиеся в «замыкании».
- Значение
winVar
в примере решения содержится в отдельной записи среды для каждого вызова forEach
делает аргумент своей функции - различные значения, сгенерированные в последовательных вызовах, не перезаписывают друг друга. - Функции onload и
setTimeout
callback являются разными объектами функций в отдельных замыканиях. Обратный вызов setTimeout
имеет доступ к записям окружения своей родительской функции onload
, которая имеет доступ к записям записи окружения своей родительской функции открытия вкладок. - Ссылка
tabWin
в обратном вызове таймера в конечном итоге разрешается привязка идентификатора, содержащегося в записи среды аргумента функции forEach
, открывшего окно вкладки при вызове.