Я столкнулся с проблемой закрытия дочернего окна внутри обратного вызова setTimeout в JavaScript. Несмотря на успешное открытие дочернего окна с помощью window.open, я не могу получить доступ к переменной newChild в функции обратного вызова setTimeout.
Вот упрощенная версия кода, с которым я работаю:
import { useState } from "react";
const useButton = () => {
const openChildWindow = () => {
const newChild = window.open(
"https://www.google.com/",
"",
"toolbar=0,status=0,width=626,height=436"
);
setTimeout(() => {
newChild.close();
}, 3000);
};
return {
openChildWindow,
};
};
Я озадачен тем, почему переменная newChild недоступна в обратном вызове setTimeout. Может ли кто-нибудь просветить меня, почему это происходит, и предложить решение этой проблемы?
Спасибо заранее за вашу помощь!
newChild.close(); выходит за пределы функции setTImeout, поэтому внутри нее не существует. то есть openChildWindow запускается и заканчивается до запуска setTimeout
@MarkSchultheiss, это не мой опыт. Новое окно все еще существует и его можно закрыть, если оно готово к закрытию (чего нет у google.com, но могут быть и другие веб-сайты).
@AHaworth Достаточно справедливо; Я тестировал фрагмент и забыл, что этот сайт блокирует их (значение null, если вы console.info(newChild) в функции перед закрытием; это также может иметь место, например, если сайт заблокирован внутри брандмауэра.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


С этим может возникнуть несколько проблем.
Однако наиболее распространенной проблемой является то, что новое открытое окно имеет другое происхождение.
Window.open после успешного открытия нового окна возвращает прокси-объект для нового окна. Мы можем использовать этот объект для управления новым окном, только если соблюдена политика одинакового происхождения (оба окна находятся в одном и том же источнике).
Я попробовал и протестировал код на странице stackoverflow. Сделанные шаги:
const newChild = window.open(
"https://stackoverflow.com/",
"",
"toolbar=0,status=0,width=626,height=436"
);
console.info("newchild value : ", newChild);
setTimeout(() => {
console.info(newChild.close);
newChild.close();
}, 3000);Я попытался воспроизвести описанную выше проблему и узнал, что вы вернули openChildWindow внутри компонента useButton. По сути, нет необходимости в оконном компоненте. поскольку window.open() откроет интерфейс браузера, я обновил приведенный ниже код, который вы можете скопировать и попробовать в codeSandbox.
function App() {
const UseButton = () => {
const newChild = window.open(
"https://stackoverflow.com/",
"",
"toolbar=0,status=0,width=626,height=436",
);
if (newChild) {
setTimeout(() => {
if (!newChild.closed) {
newChild.close();
}
}, 3000);
} else {
console.info("Failed to open child window. Pop-up blocked?");
}
};
return (
<>
<button onClick = {UseButton}>UseButton</button>
</>
);
}
export default App;
Ваш код работает нормально и так. Проблема, которую вы видите, заключается в том, что https://www.google.com/ не позволяет окну закрыться.
Попробуйте свой код с другими URL-адресами и посмотрите. Два, которые я тестировал и которые работали нормально:
Я подозреваю, что вы можете получить к нему доступ. Какая ошибка в вашей консоли разработчика? Попробуйте что-нибудь менее безопасное, чем google.com, и вы обнаружите, что, вероятно, все в порядке.