问题
I need to implement an async singleton, that creates a single instance of a class that requires asynchronous operations in order to pass arguments to the constructor. I have the following code:
class AsyncComp {
constructor(x, y) {
this.x = x;
this.y = y;
}
// A factory method for creating the async instance
static async createAsyncInstance() {
const info = await someAsyncFunction();
return new AsyncComp(info.x, info.y);
}
// The singleton method
static getAsyncCompInstance() {
if (asyncCompInstance) return asyncCompInstance;
asyncCompInstance = AsyncComp.createAsyncInstance();
return asyncCompInstance;
}
}
The code seems to work fine, as long as the promise fulfils. If, however, the promise is rejected the next calls to getAsyncCompInstance()
will return the unfulfilled promise object, which means that it will not be possible to retry the creation of the object.
How can I solve this?
回答1:
So after thinking about a couple of possible solution, I decided to wrap the asynchronous call in createAsyncInstance()
with a try/catch
block, and if it failed, set asyncCompInstance
back to be null, and throw the error the occurred. This way, if the object creation failed, the caller can call getAsyncCompInstance()
again to try to get an instance of the class:
class AsyncComp {
constructor(x, y) {
this.x = x;
this.y = y;
}
// A factory method for creating the async instance
static async createAsyncInstance() {
try {
const info = await someAsyncFunction();
return new AsyncComp(info.x, info.y);
}
catch (err) {
asyncCompInstance = null;
throw err;
}
}
// The singleton method
static getAsyncCompInstance() {
if (asyncCompInstance) return asyncCompInstance;
asyncCompInstance = AsyncComp.createAsyncInstance();
return asyncCompInstance;
}
}
I know this is not the cleanest code, and specifically not the classic factory pattern implementation, but this is the best I could come up with at the moment. Would love to hear comments/suggestions on this solution.
来源:https://stackoverflow.com/questions/59612076/creating-an-async-singletone-in-javascript