From e20f76c3b17ebb88416820bda6f2ab108e836517 Mon Sep 17 00:00:00 2001 From: "Manu Mtz.-Almeida" Date: Sat, 24 Mar 2018 03:24:57 +0100 Subject: [PATCH] refactor(all): async/await --- core/src/components/gesture/gesture.tsx | 6 +-- .../infinite-scroll/infinite-scroll.tsx | 18 +++---- core/src/components/loading/loading.tsx | 12 ++--- .../components/menu-toggle/menu-toggle.tsx | 40 ++++++++-------- core/src/components/menu/menu.tsx | 41 ++++++---------- core/src/components/modal/modal.tsx | 13 +++-- core/src/components/picker/picker.tsx | 13 +++-- core/src/components/popover/popover.tsx | 13 +++-- core/src/components/router/router.tsx | 48 +++++++++---------- core/src/utils/overlays.ts | 47 +++++++++--------- 10 files changed, 113 insertions(+), 138 deletions(-) diff --git a/core/src/components/gesture/gesture.tsx b/core/src/components/gesture/gesture.tsx index f0676b83b8..a5f608132f 100644 --- a/core/src/components/gesture/gesture.tsx +++ b/core/src/components/gesture/gesture.tsx @@ -93,12 +93,12 @@ export class Gesture { }; } - componentWillLoad() { - return this.gestureCtrl.create({ + async componentWillLoad() { + this.gesture = await this.gestureCtrl.create({ name: this.gestureName, priority: this.gesturePriority, disableScroll: this.disableScroll - }).then((gesture) => this.gesture = gesture); + }); } componentDidLoad() { diff --git a/core/src/components/infinite-scroll/infinite-scroll.tsx b/core/src/components/infinite-scroll/infinite-scroll.tsx index c355e11946..6af326bc3e 100644 --- a/core/src/components/infinite-scroll/infinite-scroll.tsx +++ b/core/src/components/infinite-scroll/infinite-scroll.tsx @@ -15,10 +15,9 @@ export class InfiniteScroll { private thrPx = 0; private thrPc = 0; - private scrollEl: HTMLIonScrollElement|null = null; + private scrollEl: HTMLIonScrollElement|undefined; private didFire = false; private isBusy = false; - private init = false; @Element() private el: HTMLElement; @State() isLoading = false; @@ -82,19 +81,14 @@ export class InfiniteScroll { */ @Event() ionInfinite: EventEmitter; - componentWillLoad() { + async componentWillLoad() { const scrollEl = this.el.closest('ion-scroll'); - return scrollEl.componentOnReady().then((el) => { - this.scrollEl = el; - }); + if (scrollEl) { + this.scrollEl = await scrollEl.componentOnReady(); + } } componentDidLoad() { - if (this.init) { - console.warn('instance was already initialized'); - return; - } - this.init = true; this.thresholdChanged(this.threshold); this.enableScrollEvents(!this.disabled); if (this.position === Position.Top) { @@ -103,7 +97,7 @@ export class InfiniteScroll { } componentDidUnload() { - this.scrollEl = null; + this.scrollEl = undefined; } @Listen('scroll', {enabled: false}) diff --git a/core/src/components/loading/loading.tsx b/core/src/components/loading/loading.tsx index 9faea49d35..bd45bdad01 100644 --- a/core/src/components/loading/loading.tsx +++ b/core/src/components/loading/loading.tsx @@ -144,12 +144,12 @@ export class Loading implements OverlayInterface { * Present the loading overlay after it has been created. */ @Method() - present(): Promise { - return present(this, 'loadingEnter', iosEnterAnimation, mdEnterAnimation, undefined).then(() => { - if (this.duration > 0) { - this.durationTimeout = setTimeout(() => this.dismiss(), this.duration + 10); - } - }); + async present(): Promise { + await present(this, 'loadingEnter', iosEnterAnimation, mdEnterAnimation, undefined); + + if (this.duration > 0) { + this.durationTimeout = setTimeout(() => this.dismiss(), this.duration + 10); + } } /** diff --git a/core/src/components/menu-toggle/menu-toggle.tsx b/core/src/components/menu-toggle/menu-toggle.tsx index d04bc1c834..a6c418e9c1 100644 --- a/core/src/components/menu-toggle/menu-toggle.tsx +++ b/core/src/components/menu-toggle/menu-toggle.tsx @@ -24,31 +24,29 @@ export class MenuToggle { } @Listen('child:click') - onClick() { - getMenuController().then(menuCtrl => { - if (menuCtrl) { - const menu = menuCtrl.get(this.menu); - if (menu && menu.isActive()) { - return menuCtrl.toggle(this.menu); - } + async onClick() { + const menuCtrl = await getMenuController(); + if (menuCtrl) { + const menu = menuCtrl.get(this.menu); + if (menu && menu.isActive()) { + return menuCtrl.toggle(this.menu); } - return false; - }); + } + return false; } @Listen('body:ionMenuChange') @Listen('body:ionSplitPaneVisible') - updateVisibility() { - return getMenuController().then(menuCtrl => { - if (menuCtrl) { - const menu = menuCtrl.get(this.menu); - if (menu && menu.isActive()) { - this.visible = true; - return; - } + async updateVisibility() { + const menuCtrl = await getMenuController(); + if (menuCtrl) { + const menu = menuCtrl.get(this.menu); + if (menu && menu.isActive()) { + this.visible = true; + return; } - this.visible = false; - }); + } + this.visible = false; } hostData() { @@ -62,10 +60,10 @@ export class MenuToggle { } -function getMenuController(): Promise { +function getMenuController(): Promise { const menuControllerElement = document.querySelector('ion-menu-controller'); if (!menuControllerElement) { - return Promise.resolve(null); + return Promise.resolve(undefined); } return menuControllerElement.componentOnReady(); } diff --git a/core/src/components/menu/menu.tsx b/core/src/components/menu/menu.tsx index 1e57ffc7df..e46936897b 100644 --- a/core/src/components/menu/menu.tsx +++ b/core/src/components/menu/menu.tsx @@ -14,7 +14,6 @@ import { Side, assert, isRightSide } from '../../utils/helpers'; }) export class Menu { - private gestureBlocker: string; private animation: Animation|undefined; private isPane = false; private _isOpen = false; @@ -121,10 +120,8 @@ export class Menu { @Event() protected ionMenuChange: EventEmitter; - componentWillLoad() { - return this.lazyMenuCtrl.componentOnReady().then(menu => { - this.menuCtrl = menu; - }); + async componentWillLoad() { + this.menuCtrl = await this.lazyMenuCtrl.componentOnReady(); } componentDidLoad() { @@ -212,16 +209,17 @@ export class Menu { return this.menuCtrl._setOpen(this, shouldOpen, animated); } - _setOpen(shouldOpen: boolean, animated = true): Promise { + async _setOpen(shouldOpen: boolean, animated = true): Promise { // If the menu is disabled or it is currenly being animated, let's do nothing if (!this.isActive() || this.isAnimating || (shouldOpen === this._isOpen)) { - return Promise.resolve(this._isOpen); + return this._isOpen; } this.beforeAnimation(); - return this.loadAnimation() - .then(() => this.startAnimation(shouldOpen, animated)) - .then(() => this.afterAnimation(shouldOpen)); + await this.loadAnimation(); + await this.startAnimation(shouldOpen, animated); + await this.afterAnimation(shouldOpen); + return shouldOpen; } @Method() @@ -229,24 +227,22 @@ export class Menu { return !this.disabled && !this.isPane; } - private loadAnimation(): Promise { + private async loadAnimation(): Promise { // Menu swipe animation takes the menu's inner width as parameter, // If `offsetWidth` changes, we need to create a new animation. const width = this.menuInnerEl.offsetWidth; if (width === this.width && this.animation !== null) { - return Promise.resolve(); + return; } + this.width = width; + // Destroy existing animation if (this.animation) { this.animation.destroy(); this.animation = null; } - this.width = width; - // Create new animation - return this.menuCtrl.createAnimation(this.type, this).then(ani => { - this.animation = ani; - }); + this.animation = await this.menuCtrl.createAnimation(this.type, this); } private startAnimation(shouldOpen: boolean, animated: boolean): Promise { @@ -359,7 +355,7 @@ export class Menu { this.isAnimating = true; } - private afterAnimation(isOpen: boolean): boolean { + private afterAnimation(isOpen: boolean) { assert(this.isAnimating, '_before() should be called while animating'); // keep opening/closing the menu disabled for a touch more yet @@ -373,9 +369,6 @@ export class Menu { this.enableListener(this, 'body:click', isOpen); if (isOpen) { - // disable swipe to go back gesture - this.gestureBlocker = GESTURE_BLOCKER; - // add css class this.contentEl.classList.add(MENU_CONTENT_OPEN); @@ -383,9 +376,6 @@ export class Menu { this.ionOpen.emit(); } else { - // enable swipe to go back gesture - this.gestureBlocker = null; - // remove css classes this.el.classList.remove(SHOW_MENU); this.contentEl.classList.remove(MENU_CONTENT_OPEN); @@ -394,7 +384,6 @@ export class Menu { // emit close event this.ionClose.emit(); } - return isOpen; } private updateState() { @@ -461,7 +450,6 @@ export class Menu { 'threshold': 10, 'attachTo': 'window', 'disableScroll': true, - 'block': this.gestureBlocker }}/> ]); } @@ -482,7 +470,6 @@ function checkEdgeSide(posX: number, isRightSide: boolean, maxEdgeStart: number) const SHOW_MENU = 'show-menu'; const SHOW_BACKDROP = 'show-backdrop'; const MENU_CONTENT_OPEN = 'menu-content-open'; -const GESTURE_BLOCKER = 'goback-swipe'; export interface MenuChangeEvent { target: HTMLIonMenuElement; diff --git a/core/src/components/modal/modal.tsx b/core/src/components/modal/modal.tsx index 1863bf92a2..46d0f88e49 100644 --- a/core/src/components/modal/modal.tsx +++ b/core/src/components/modal/modal.tsx @@ -164,7 +164,7 @@ export class Modal implements OverlayInterface { * Present the modal overlay after it has been created. */ @Method() - present(): Promise { + async present(): Promise { if (this.presented) { return Promise.resolve(); } @@ -177,18 +177,17 @@ export class Modal implements OverlayInterface { ...getClassList(this.cssClass), 'ion-page' ]; - return attachComponent(this.delegate, container, this.component, classes, data) - .then(el => this.usersElement = el) - .then(() => present(this, 'modalEnter', iosEnterAnimation, mdEnterAnimation)); + this.usersElement = await attachComponent(this.delegate, container, this.component, classes, data); + return present(this, 'modalEnter', iosEnterAnimation, mdEnterAnimation); } /** * Dismiss the modal overlay after it has been presented. */ @Method() - dismiss(data?: any, role?: string): Promise { - return dismiss(this, data, role, 'modalLeave', iosLeaveAnimation, mdLeaveAnimation) - .then(() => detachComponent(this.delegate, this.usersElement)); + async dismiss(data?: any, role?: string): Promise { + await dismiss(this, data, role, 'modalLeave', iosLeaveAnimation, mdLeaveAnimation); + await detachComponent(this.delegate, this.usersElement); } /** diff --git a/core/src/components/picker/picker.tsx b/core/src/components/picker/picker.tsx index 7d6e7082d0..88acabb0dd 100644 --- a/core/src/components/picker/picker.tsx +++ b/core/src/components/picker/picker.tsx @@ -144,13 +144,12 @@ export class Picker implements OverlayInterface { * Present the picker overlay after it has been created. */ @Method() - present(): Promise { - return present(this, 'pickerEnter', iosEnterAnimation, iosEnterAnimation, undefined).then(() => { - // If there is a duration, dismiss after that amount of time - if (this.duration > 10) { - this.durationTimeout = setTimeout(() => this.dismiss(), this.duration); - } - }); + async present(): Promise { + await present(this, 'pickerEnter', iosEnterAnimation, iosEnterAnimation, undefined); + + if (this.duration > 0) { + this.durationTimeout = setTimeout(() => this.dismiss(), this.duration); + } } /** diff --git a/core/src/components/popover/popover.tsx b/core/src/components/popover/popover.tsx index 55100c13ab..858d1dda98 100644 --- a/core/src/components/popover/popover.tsx +++ b/core/src/components/popover/popover.tsx @@ -174,7 +174,7 @@ export class Popover implements OverlayInterface { * Present the popover overlay after it has been created. */ @Method() - present(): Promise { + async present(): Promise { if (this.presented) { return Promise.reject('df'); } @@ -187,18 +187,17 @@ export class Popover implements OverlayInterface { ...getClassList(this.cssClass), 'popover-viewport' ]; - return attachComponent(this.delegate, container, this.component, classes, data) - .then(el => this.usersElement = el) - .then(() => present(this, 'popoverEnter', iosEnterAnimation, mdEnterAnimation, this.ev)); + this.usersElement = await attachComponent(this.delegate, container, this.component, classes, data); + return present(this, 'popoverEnter', iosEnterAnimation, mdEnterAnimation, this.ev); } /** * Dismiss the popover overlay after it has been presented. */ @Method() - dismiss(data?: any, role?: string): Promise { - return dismiss(this, data, role, 'popoverLeave', iosLeaveAnimation, mdLeaveAnimation, this.ev) - .then(() => detachComponent(this.delegate, this.usersElement)); + async dismiss(data?: any, role?: string): Promise { + await dismiss(this, data, role, 'popoverLeave', iosLeaveAnimation, mdLeaveAnimation, this.ev); + await detachComponent(this.delegate, this.usersElement); } /** diff --git a/core/src/components/router/router.tsx b/core/src/components/router/router.tsx index 620c75d757..d0fb36da48 100644 --- a/core/src/components/router/router.tsx +++ b/core/src/components/router/router.tsx @@ -80,29 +80,26 @@ export class Router { } @Method() - navChanged(isPop: boolean): Promise { + async navChanged(isPop: boolean): Promise { if (this.busy) { - return Promise.resolve(false); + return false; } console.debug('[IN] nav changed -> update URL'); const { ids, pivot } = readNavState(document.body); const chain = routerIDsToChain(ids, this.routes); if (!chain) { console.warn('no matching URL for ', ids.map(i => i.id)); - return Promise.resolve(false); + return false; } const path = chainToPath(chain); this.setPath(path, isPop); - const promise = (chain.length > ids.length) - ? this.writeNavState(pivot, chain.slice(ids.length), 0) - : Promise.resolve(true); - - return promise.then(() => { - this.emitRouteChange(path, null); - return true; - }); + if (chain.length > ids.length) { + await this.writeNavState(pivot, chain.slice(ids.length), 0); + } + this.emitRouteChange(path, null); + return true; } @Method() @@ -113,9 +110,9 @@ export class Router { return this.writeNavStateRoot(path, backDirection ? -1 : 1); } - private writeNavStateRoot(path: string[], direction: number): Promise { + private async writeNavStateRoot(path: string[], direction: number): Promise { if (this.busy) { - return Promise.resolve(false); + return false; } const redirect = routeRedirect(path, this.redirects); let redirectFrom: string[] = null; @@ -125,23 +122,26 @@ export class Router { path = redirect.to; } const chain = routerPathToChain(path, this.routes); - return this.writeNavState(document.body, chain, direction).then(changed => { - if (changed) { - this.emitRouteChange(path, redirectFrom); - } - return changed; - }); + const changed = await this.writeNavState(document.body, chain, direction); + if (changed) { + this.emitRouteChange(path, redirectFrom); + } + return changed; } - private writeNavState(node: any, chain: RouteChain, direction: number): Promise { + private async writeNavState(node: any, chain: RouteChain, direction: number): Promise { if (this.busy) { - return Promise.resolve(false); + return false; } - this.busy = true; - return writeNavState(node, chain, 0, direction).then(changed => { + try { + this.busy = true; + const changed = await writeNavState(node, chain, 0, direction); this.busy = false; return changed; - }); + } catch (e) { + this.busy = false; + throw e; + } } private setPath(path: string[], isPop: boolean) { diff --git a/core/src/utils/overlays.ts b/core/src/utils/overlays.ts index afedfd9e59..ec2e364baf 100644 --- a/core/src/utils/overlays.ts +++ b/core/src/utils/overlays.ts @@ -53,7 +53,7 @@ export function removeLastOverlay(overlays: OverlayMap) { return toRemove ? toRemove.dismiss() : Promise.resolve(); } -export function present( +export async function present( overlay: OverlayInterface, name: string, iosEnterAnimation: AnimationBuilder, @@ -61,7 +61,7 @@ export function present( opts?: any ) { if (overlay.presented) { - return Promise.resolve(); + return; } overlay.presented = true; overlay.willPresent.emit(); @@ -71,12 +71,12 @@ export function present( ? overlay.enterAnimation : overlay.config.get(name, overlay.mode === 'ios' ? iosEnterAnimation : mdEnterAnimation); - return overlayAnimation(overlay, animationBuilder, overlay.el, opts).then(() => { - overlay.didPresent.emit(); - }); + await overlayAnimation(overlay, animationBuilder, overlay.el, opts); + + overlay.didPresent.emit(); } -export function dismiss( +export async function dismiss( overlay: OverlayInterface, data: any|undefined, role: string|undefined, @@ -86,7 +86,7 @@ export function dismiss( opts?: any ): Promise { if (!overlay.presented) { - return Promise.resolve(); + return; } overlay.presented = false; @@ -96,36 +96,35 @@ export function dismiss( ? overlay.leaveAnimation : overlay.config.get(name, overlay.mode === 'ios' ? iosLeaveAnimation : mdLeaveAnimation); - return overlayAnimation(overlay, animationBuilder, overlay.el, opts).then(() => { - overlay.didDismiss.emit({data, role}); - overlay.el.remove(); - }); + await overlayAnimation(overlay, animationBuilder, overlay.el, opts); + + overlay.didDismiss.emit({data, role}); + overlay.el.remove(); } -function overlayAnimation( +async function overlayAnimation( overlay: OverlayInterface, animationBuilder: AnimationBuilder, baseEl: HTMLElement, opts: any ): Promise { + if (overlay.keyboardClose) { + closeKeyboard(); + } if (overlay.animation) { overlay.animation.destroy(); overlay.animation = undefined; } - if (overlay.keyboardClose) { - closeKeyboard(); + const animation = overlay.animation = await overlay.animationCtrl.create(animationBuilder, baseEl, opts); + overlay.animation = animation; + if (!overlay.willAnimate) { + animation.duration(0); } - return overlay.animationCtrl.create(animationBuilder, baseEl, opts).then(animation => { - overlay.animation = animation; - if (!overlay.willAnimate) { - animation.duration(0); - } - return animation.playAsync(); - }).then(animation => { - animation.destroy(); - overlay.animation = undefined; - }); + await animation.playAsync(); + + animation.destroy(); + overlay.animation = undefined; } export function autoFocus(containerEl: HTMLElement): HTMLElement|null {