// Declare the class
class A {
// Declare class constructor
constructor() {
// We didn't finish the async job yet
this.initialized = false;
// Simulates async job, it takes 5 seconds to have it done
setTimeout(() => {
this.initialized = true;
}, 5000);
}
// do something usefull here - thats a normal method
useful() {
// but only if initialization was OK
if (this.initialized) {
console.log("I am doing something useful here")
// otherwise throw an error which will be caught by the promise catch
} else {
throw new Error("I am not initialized!");
}
}
}
// factory for common, extensible class - that's the reason for the constructor parameter
// it can be more sophisticated and accept also params for constructor and pass them there
// also, the timeout is just an example, it will wait for about 10s (1000 x 10ms iterations
function factory(construct) {
// create a promise
var aPromise = new Promise(
function(resolve, reject) {
// construct the object here
var a = new construct();
// setup simple timeout
var timeout = 1000;
// called in 10ms intervals to check if the object is initialized
function waiter() {
if (a.initialized) {
// if initialized, resolve the promise
resolve(a);
} else {
// check for timeout - do another iteration after 10ms or throw exception
if (timeout > 0) {
timeout--;
setTimeout(waiter, 10);
} else {
throw new Error("Timeout!");
}
}
}
// call the waiter, it will return almost immediately
waiter();
}
);
// return promise of the object being created and initialized
return a Promise;
}
// this is some async function to create object of A class and do something with it
async function createObjectAndDoSomethingUseful() {
// try/catch to capture exceptions during async execution
try {
// create object and wait until its initialized (promise resolved)
var a = await factory(A);
// then do something usefull
a.useful();
} catch(e) {
// if class instantiation failed from whatever reason, timeout occured or useful was called before the object finished its initialization
console.error(e);
}
}
// now, perform the action we want
createObjectAndDoSomethingUsefull();
// spaghetti code is done here, but async probably still runs
class Foo {
public Ready: Promise.IThenable<any>;
constructor() {
...
this.Ready = new Promise((resolve, reject) => {
$.ajax(...).then(result => {
// use result
resolve(undefined);
}).fail(reject);
});
}
}
var foo = new Foo();
foo.Ready.then(() => {
// do stuff that needs foo to be ready, eg apply bindings
});
// keep going with other stuff that doesn't need to wait for foo
// using await
// code that doesn't need foo to be ready
await foo.Ready;
// code that needs foo to be ready
class MyClass {
private mMember: Something;
// make private if possible; I can't in TS 1.8
constructor() {
}
public static CreateAsync = async () => {
const me = new MyClass();
me.mMember = await SomeFunctionAsync();
return me;
};
}
class MyClass {
constructor(){
this.#fetchResolved = this.fetch()
}
#fetchResolved: Promise<void>;
fetch = async (): Promise<void> => {
return new Promise(resolve => resolve()) // save data to class property or simply add it by resolve() to #fetchResolved reference
}
isConstructorDone = async (): boolean => {
await this.#fetchResolved;
return true; // or any other data depending on constructor finish the job
}
}
使用方法:
const data = new MyClass();
const field = await data.isConstructorDone();