У меня странная проблема с реализацией JS FB-SDK. Все работает безупречно, за исключением IE 11. Метод FB.loginофициальный JS-API, который получает обратный вызов, запускает его дважды после появления диалогового окна OAuth и авторизации приложения пользователем. В первый раз он возвращает ответ с параметром authResponse как undefined, во второй раз он имеет все ожидаемые значения.
Я совершенно не понимаю, почему это происходит. Я дважды и трижды проверил, что FB.login нигде не вызывается дважды. Кто-нибудь когда-нибудь преодолевал этот сценарий или заставлял работать вход через FB с IE?
Он отлично работает в Edge, Firefox, Chrome и даже в мобильных браузерах: chrome и safari в iOS, Android Chrome.
Я предоставляю минимальную воспроизводимую демонстрацию кода.
### index.html
<!DOCTYPE html>
<html lang = "en" >
<head>
<meta charset = "UTF-8">
<title>FB IE 11</title>
</head>
<body>
<div id = "fb-root"></div>
<button
id = "fblogin">
Sign in with Facebook
</button>
<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.8/angular.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.9.1/underscore-min.js'></script>
<script src = "./script.js"></script>
</body>
</html>
### script.js
(function($) {
var EP = { facebook: {} }
EP.facebook.init_was_called = false;
EP.facebook.promise = $.Deferred();
EP.facebook.connected = false;
EP.facebook.emailDeclined = false;
EP.facebook.loginRetryCount = 0;
window.fbAsyncInit = () => {
console.info("window.fbAsyncInit callback triggered by Facebook SDK");
window.FB.init({
appId: "418117192377109", // should be your app id when testing
cookie: true, // Store fbsr_xxx cookie
xfmbl: false,
version: "v3.2",
status: true // Fetch user's facebook login status
});
EP.facebook.promise.resolve();
};
// Use this to wrap any calls where we're not sure the FB api has been bootstrapped
EP.facebook.afterFacebookInitialized = callback => {
return $.when(EP.facebook.promise).then(callback);
};
$(function() {
// Always parseFBML
EP.facebook.afterFacebookInitialized().done(function() {
window.FB.XFBML.parse();
});
if (EP.facebook.init_was_called) {
return;
}
EP.facebook.init_was_called = true;
// This only needs to be called once per full page load (on The Post and when showing login screen)
$.getScript("https://connect.facebook.net/en_US/sdk.js");
});
var Facebook = function() {
var fbLoginParams;
if (!window.FB) {
console.info('FB not loaded yet!')
return;
} else if (EP.facebook.connected && !EP.facebook.emailDeclined) {
console.info('Already logged in to FB')
return;
} else {
fbLoginParams = {
scope: "email"
};
if (EP.facebook.emailDeclined) {
fbLoginParams.auth_type = "rerequest";
}
return window.FB.login(function(response) {
console.info("FB.login response: ", response);
if (response.authResponse) {
EP.facebook.connected = true;
return
} else {
return;
}
}, fbLoginParams);
}
}
$("#fblogin").on("click", Facebook)
})(jQuery)
Чтобы это работало, он должен обслуживаться с сервера с доменом, отличным от локальный хост, из-за ограничений приложения fb и обслуживаться через https. Я использовал нгрок для сопоставления URL-адреса https с моим локальным сервером разработки. Локальный сервер разработки был просто пакет, запущенным с выполнения parcel build index.html, а затем parcel index.html. Конечно, вам нужно настроить FB-приложение разработчика с действительным URI перенаправления OAuth (ngrok). Помните также, что вы должны выйти из Facebook, прежде чем тестировать это. Вот результаты после входа в FB и авторизации тестового приложения FB:
Вот они, 2 ответа, великолепные!
Спасибо
@YuZhou попытается создать воспроизводимый пример и вернуться с ним!
@YuZhou Ну вот, смотрите мои правки. Надеюсь, этот минимальный пример работает для вас. Пытался использовать codeandbox, но не работает с IE11, поэтому... не оставил мне другого выбора, кроме как вставить минимальный необходимый код с небольшими инструкциями о том, как попытаться воспроизвести среду





Я воспроизвел проблему на своей стороне. После использования fiddler для сравнения сетевого трафика между IE и другими браузерами я обнаружил, что шаг входа будет направлен на ссылку-> https://www.facebook.com/dialog/close_window/?app_id=xxxxxxxxx&connect=0 в IE11. Вы можете увидеть, как эта страница мигает при входе в IE:
В других браузерах этого не будет. Я думаю, что это причина двух ответов. Это может быть какая-то проблема с IE, или API разработан так в IE.
Можете ли вы придумать обходной путь, чтобы игнорировать первый ответ из примера кода, учитывая, что он очень похож на тот же ответ, который происходит, когда пользователь отклоняет авторизацию или закрывает диалоговое окно без предоставления доступа?
Единственный обходной путь, который я могу найти, - это поставить console.info("FB.login response: ", response); после if (response.authResponse) {, тогда ответ появляется только при успешном подключении.
Хм, это не помешает. Дело в том, что на более высоком уровне я оборачиваю это в промисы, и когда приходит неопределенный ответ, что иногда бывает в случае закрытых диалогов по желанию пользователя, я отклоняю промис и определенные триггеры бизнес-логики, которые влияют на пользовательский интерфейс. . Пользователи IE 11 никогда не смогут подключиться или увидеть согласованный пользовательский интерфейс, поскольку обещание уже было отклонено, несмотря на получение второго ответа.
Проблема была в ошибке в facebook! Я разместил в их справочном центре сообщения об ошибках, описал проблему, и они ее исправили. Разрешение на испанском языке, но вы можете проверить здесь
Конечно, они не указали причину проблемы, но сейчас проверили, и она работает так, как ожидалось.
Я не могу воспроизвести проблему только с приведенным выше кодом. Я пытаюсь скомпилировать код coffeescript в код javascript, но получаю ошибку. Предоставьте больше кодов, связанных с проблемой, включая html-коды, скрипты, полифиллы и т. д. Вы можете обратиться к этому, чтобы предоставить минимальный воспроизводимый пример.