small refactoring to prepare async work

This commit is contained in:
Géry Debongnie
2019-02-07 12:10:44 +01:00
parent 87facd993b
commit f648f47197
3 changed files with 34 additions and 19 deletions
+10 -6
View File
@@ -112,12 +112,12 @@ export class Component<
//--------------------------------------------------------------------------
async mount(target: HTMLElement): Promise<void> {
await this._start();
await this.render();
if (!this.el) {
const vnode = await this._start();
if (this.__widget__.isDestroyed) {
// widget was destroyed before we get here...
return;
}
this._patch(vnode);
target.appendChild(this.el!);
if (document.body.contains(target)) {
@@ -204,13 +204,16 @@ export class Component<
return;
}
const vnode = await this._render();
this._patch(vnode);
}
private _patch(vnode) {
this.__widget__.vnode = patch(
this.__widget__.vnode || document.createElement(vnode.sel!),
vnode
);
}
private async _start(): Promise<void> {
private async _start(): Promise<VNode> {
await this.willStart();
if (!this.__widget__.isDestroyed) {
this.__widget__.isStarted = true;
@@ -218,9 +221,10 @@ export class Component<
if (this.inlineTemplate) {
this.env.qweb.addTemplate(this.inlineTemplate, this.inlineTemplate, true);
}
return this._render();
}
private async _render(): Promise<VNode> {
async _render(): Promise<VNode> {
const promises: Promise<void>[] = [];
const template = this.inlineTemplate || this.template;
let vnode = this.env.qweb.render(template, this, { promises });
+8 -13
View File
@@ -1,8 +1,10 @@
import { Component, WEnv } from "../../src/ts/core/component";
import {
makeDeferred,
makeTestFixture,
makeTestWEnv,
nextMicroTick,
nextTick,
normalize
} from "../helpers";
@@ -107,9 +109,9 @@ describe("basic widget properties", () => {
async willStart() {
this.updateState({});
}
async render() {
async _render() {
renderCalls++;
return super.render();
return super._render();
}
}
const widget = new TestW(env);
@@ -448,14 +450,11 @@ describe("destroy method", () => {
});
test("destroying a widget before willStart is done", async () => {
let resolve;
let def = makeDeferred();
let isRendered = false;
let p: Promise<void> = new Promise(function(r) {
resolve = r;
});
class DelayedWidget extends Widget {
willStart() {
return p;
return def;
}
}
expect(fixture.innerHTML).toBe("");
@@ -468,12 +467,8 @@ describe("destroy method", () => {
expect(widget.__widget__.isMounted).toBe(false);
expect(widget.__widget__.isStarted).toBe(false);
expect(widget.__widget__.isDestroyed).toBe(true);
resolve();
// Note: should we abandon await and not have to do this?
// TODO: talk to vsc
await nextMicroTick();
await nextMicroTick();
await nextMicroTick();
def.resolve();
await nextTick();
expect(widget.__widget__.isStarted).toBe(false);
expect(widget.__widget__.isMounted).toBe(false);
+16
View File
@@ -199,3 +199,19 @@ export function nextMicroTick(): Promise<void> {
export function nextTick(): Promise<void> {
return new Promise(resolve => setTimeout(resolve));
}
interface Deferred extends Promise<any> {
resolve(val?: any): void;
reject(): void;
}
export function makeDeferred(): Deferred {
let resolve, reject;
let def = new Promise((_resolve, _reject) => {
resolve = _resolve;
reject = _reject;
});
(<Deferred>def).resolve = resolve;
(<Deferred>def).reject = reject;
return <Deferred>def;
}