【发布时间】:2022-02-14 23:51:13
【问题描述】:
我在一个奇怪的网站上工作,我只需要将表单发送到 firestore 并将 pdf 文件保存到 firestorage。 甚至不运行任何服务器端代码,只在最终客户端上运行 html 和 JS。 我的组织只会提供运行 html、CSS 和 JS 的 apache 服务器路径。 稍后我需要阅读,但我是唯一具有读取权限的用户,所以这没什么大不了的,因为我将在我的 node.js CLI 上本地运行它。
但我期待着让我的代码尽可能安全和高效,即使我 60% 的时间都不知道自己在做什么。
在线阅读文档和代码后,我意识到我在执行 onAuthStateChanged() 时并没有执行 unsubscribe()。 通过搜索 JS 上的内存泄漏,我发现一个人说如果我想让某些东西在内存中保持存在,那么我不应该取消订阅它。但正如我所说,我不知道自己在做什么。
这是我的一些 .js 和 login.html 我担心 4 件事,我开始吧:
- 我应该在我的登出 onAuthStateChanged 结束后取消订阅()吗?如果有,在哪里?
- 可以在 window.onload 中设置所有这些代码吗?
- 我是否应该将此代码拆分为模块,以便我可以重新使用 initializeApp() 和其他重复代码,否则不推荐这样做,因为我使用 CDN 来导入 firebase 模块而不是使用 import 语句。
- 我应该在我的每一个 html 页面上执行 initializeApp() 吗?还是在登录时执行一次并强制用户通过 vanilla JS 登录将是可行的方法?
window.onload = () => { //Config and init fb var firebaseConfig = { //...my config }; if (!firebase.apps.length) { firebase.initializeApp(firebaseConfig) } const auth = firebase.auth(); const provider = new firebase.auth.GoogleAuthProvider(); //Get elements const signInBtn = document.getElementById("log-in-btn"); //Listeners signInBtn.onclick = () => auth.signInWithPopup(provider); //Listeners require user //sign-in-out auth.onAuthStateChanged(user => { if (user) { // signed in if (!user.email.includes('@mydomain.com')) { auth.signOut(); //maybe delete the user, haven't test it alert('Porfavor utilice su correo institucional'); } else { window.location.replace('dashboard.html'); } } else { // not signed in you will always end up here } }); }
html 都是这样的,但我有每个 html 的 JS 文件,每个 JS 配置和初始化 firebase。
<head> <meta charset="UTF-8"> <title>Login </title> <!--Project CSS--> <!--Boostrap 5--> <!--Firebase Modules--> <script src="https://www.gstatic.com/firebasejs/8.10.0/firebase-app.js"></script> <script src="https://www.gstatic.com/firebasejs/8.10.0/firebase-firestore.js"></script> <script src="https://www.gstatic.com/firebasejs/8.10.0/firebase-auth.js"></script> <script src="https://www.gstatic.com/firebasejs/8.10.0/firebase-storage.js"></script> <!--Proyect Modules--> <script src="js/login.js" defer></script> </head>
稍后在我的仪表板中这是我的方法
window.onload = () => { var firebaseConfig = { //my config }; if (!firebase.apps.length) { firebase.initializeApp(firebaseConfig) } const auth = firebase.auth(); const provider = new firebase.auth.GoogleAuthProvider(); //Get elements const signedIn = document.getElementById("toggle-w-log-in"); const signedOff = document.getElementById("toggle-w-log-off"); const signInBtn = document.getElementById("log-in-btn"); const signOutBtn = document.getElementById("log-off-btn"); const uname = document.getElementById("userName"); const userDetails = document.getElementById("userDetails"); //Events / Listeners signOutBtn.onclick = () => { auth.signOut(); window.location.replace("login.html"); }; //Events / Listeners that require user //sign-in-out auth.onAuthStateChanged(user => { if (user) { // signed in signedIn.hidden = false; signedOff.hidden = true; userDetails.innerHTML = `<b>Sesión iniciada como ${user.displayName}</b>`; var contentImgUser = document.getElementById("img-Us"); contentImgUser.setAttribute("src", user.photoURL); } else { // not signed in signedIn.hidden = true; signedOff.hidden = false; userDetails.innerHTML = ''; window.location.replace("login.html"); } }); }
最后是百万美元的问题:我是否对我的表单代码发疯了?
window.onload = () => { var firebaseConfig = { //my config }; if (!firebase.apps.length) { firebase.initializeApp(firebaseConfig) } const auth = firebase.auth(); const provider = new firebase.auth.GoogleAuthProvider(); //Get elements from dom by id //Events / Listeners //sign-in-out signOutBtn.onclick = () => { auth.signOut(); window.location.replace("login.html"); }; auth.onAuthStateChanged(user => { if (user) { // signed in signedIn.hidden = false; signedOff.hidden = true; //display the userDetails //display user name in the username field uname.value = user.displayName; } else { // not signed in signedIn.hidden = true; signedOff.hidden = false; userDetails.innerHTML = ''; window.location.replace("login.html"); } }); //save file to Firestorage then save doc to Firestore //finally set a cooldown on the button auth.onAuthStateChanged(user => { saveBtn.addEventListener("click", (event) => { event.preventDefault(); //check my required files if (requiredFields) { saveBtn.disabled = true; //some logic with my progressbar var metadata = { contentType: 'application/pdf' }; const files = document.getElementById("myfile").files; var storageRef = firebase.storage().ref(); let file = files[0]; // Upload file and metadata to the object 'pdf/filename.pdf' // Listen for state changes, errors, and completion of the upload. uploadTask.on(firebase.storage.TaskEvent.STATE_CHANGED, (snapshot) => { // Get task progress, including the number of bytes uploaded and the total number of bytes to be uploaded //some logic with the progress to fill my progressbar switch (snapshot.state) { case firebase.storage.TaskState.PAUSED: break; case firebase.storage.TaskState.RUNNING: break; } }, (error) => { switch (error.code) { case 'storage/unauthorized': break; case 'storage/canceled': break; case 'storage/unknown': break; } }, () => { // Upload completed successfully, now we can get the download URL uploadTask.snapshot.ref.getDownloadURL().then((downloadURL) => { const db = firebase.firestore().collection('mycollections'); const userUid = user.uid; const timestamp = new Date().getTime(); try { db.add({ refEvi: downloadURL, userUid: userUid, //all my fields }).then((docRef) => { artRes.innerHTML = "<b>Registro guardado con la referencia: </b>" + docRef.id; }); } catch (error) { console.log(error); artRes.innerHTML = "<b>Problema al guardar registro en la base de datos. </b>" + error; } finally { //a timer to enable my button a few secs after everything is done } }); } ); } }); }); }
是的,我只是用 cmets 替换了一些代码以使这篇文章可读。 我的 js 中有什么地方我应该取消订阅 onAuthStateChanged 吗?
【问题讨论】:
标签: javascript html firebase firebase-authentication