Skip to content

Commit

Permalink
Await in the login form, documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
corrideat committed Oct 12, 2023
1 parent 8e1701e commit 0a1cd00
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 9 deletions.
1 change: 1 addition & 0 deletions frontend/controller/actions/identity.js
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,7 @@ export default (sbp('sbp/selectors/register', {
await sbp('chelonia/storeSecretKeys', transientSecretKeys)
// IMPORTANT: we avoid using 'await' on the syncs so that Vue.js can proceed
// loading the website instead of stalling out.
// See the TODO note in startApp (main.js) for why this is not awaited
sbp('chelonia/contract/sync', contractIDs).then(async function () {
// contract sync might've triggered an async call to /remove, so wait before proceeding
await sbp('chelonia/contract/wait', contractIDs)
Expand Down
7 changes: 7 additions & 0 deletions frontend/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,13 @@ async function startApp () {
try {
if (identityContractID) {
sbp('okTurtles.events/on', CONTRACT_IS_SYNCING, initialSyncFn)
// TODO: 'gi.actions/identity/login' will return before the contract
// state is synced
// This is to continue with the following block that is setting up
// Vue.js, but as a result the login events listened for below may
// have already fired. Instead, this block should be moved below the
// Vue.js set up, and the router be updated to handle not having a login
// state initially.
await sbp('gi.actions/identity/login', { identityContractID })
}
} catch (e) {
Expand Down
28 changes: 19 additions & 9 deletions frontend/views/containers/access/LoginForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -88,25 +88,31 @@ export default ({
const username = this.form.username
let outerResolve, outerReject
// Promise to return once login finished, so that the form doesn't show
// as completed.
// See the TODO note in startApp (main.js) for how to do this more
// cleanly by having 'gi.actions/identity/login' await on the call
// to 'chelonia/contract/sync' that happens after logging in.
const finishedLoggingIn = new Promise((resolve, reject) => {
outerResolve = resolve
outerReject = reject
})
// 'gi.actions/identity/login' syncs the identity contract without
// awaiting on it, which can cause issues because this.postSubmit()
// can get called before the state for the identity contract is complete.
// To avoid these issues, we set up an event handler (on LOGIN) to call
// this.postSubmit() once the identity contract has finished syncing
// If an error occurred during login, we set up an event handler (on
// LOGIN_ERROR) to remove the login event handler.
const loginEventHandler = async ({ username: user }) => {
if (user !== username) return
const loginEventHandler = () => {
sbp('okTurtles.events/off', LOGIN_ERROR, loginErrorEventHandler)
await this.postSubmit()
this.$emit('submit-succeeded')
requestNotificationPermission()
outerResolve()
}
const loginErrorEventHandler = ({ username: user, error }) => {
if (user !== username) return
const loginErrorEventHandler = ({ error }) => {
sbp('okTurtles.events/off', LOGIN, loginEventHandler)
this.$refs.formMsg.danger(error.message)
outerReject(error)
}
sbp('okTurtles.events/once', LOGIN, loginEventHandler)
sbp('okTurtles.events/once', LOGIN_ERROR, loginErrorEventHandler)
Expand All @@ -115,6 +121,10 @@ export default ({
username,
passwordFn: wrapValueInFunction(this.form.password)
})
await finishedLoggingIn
await this.postSubmit()
this.$emit('submit-succeeded')
requestNotificationPermission()
} catch (e) {
console.error('FormLogin.vue login() error:', e)
this.$refs.formMsg.danger(e.message)
Expand Down

0 comments on commit 0a1cd00

Please sign in to comment.