aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Utils.ts12
-rw-r--r--src/client/Server.ts66
-rw-r--r--src/client/SocketStub.ts15
-rw-r--r--src/fields/Document.ts46
4 files changed, 85 insertions, 54 deletions
diff --git a/src/Utils.ts b/src/Utils.ts
index a4db94809..ccd503abe 100644
--- a/src/Utils.ts
+++ b/src/Utils.ts
@@ -41,8 +41,16 @@ export class Utils {
socket.emit(message.Message, args);
}
- public static EmitCallback<T>(socket: Socket | SocketIOClient.Socket, message: Message<T>, args: T, fn: (args: any) => any) {
- socket.emit(message.Message, args, fn);
+ public static EmitCallback<T>(socket: Socket | SocketIOClient.Socket, message: Message<T>, args: T): Promise<any>;
+ public static EmitCallback<T>(socket: Socket | SocketIOClient.Socket, message: Message<T>, args: T, fn: (args: any) => any): void;
+ public static EmitCallback<T>(socket: Socket | SocketIOClient.Socket, message: Message<T>, args: T, fn?: (args: any) => any): void | Promise<any> {
+ if (fn) {
+ socket.emit(message.Message, args, fn);
+ } else {
+ return new Promise<any>(res => {
+ socket.emit(message.Message, args, res);
+ })
+ }
}
public static AddServerHandler<T>(socket: Socket, message: Message<T>, handler: (args: T) => any) {
diff --git a/src/client/Server.ts b/src/client/Server.ts
index bbdc27397..6a47076fb 100644
--- a/src/client/Server.ts
+++ b/src/client/Server.ts
@@ -15,37 +15,45 @@ export class Server {
// Retrieves the cached value of the field and sends a request to the server for the real value (if it's not cached).
// Call this is from within a reaction and test whether the return value is FieldWaiting.
- // 'hackTimeout' is here temporarily for simplicity when debugging things.
- public static GetField(fieldid: FieldId, callback: (field: Opt<Field>) => void): Opt<Field> | FIELD_WAITING {
- let cached = this.ClientFieldsCached.get(fieldid);
- if (!cached) {
- this.ClientFieldsCached.set(fieldid, FieldWaiting);
- SocketStub.SEND_FIELD_REQUEST(fieldid, action((field: Field | undefined) => {
- let cached = this.ClientFieldsCached.get(fieldid);
- if (cached != FieldWaiting)
- callback(cached);
- else {
- if (field) {
- this.ClientFieldsCached.set(fieldid, field);
- } else {
- this.ClientFieldsCached.delete(fieldid)
+ public static GetField(fieldid: FieldId): Promise<Opt<Field>>;
+ public static GetField(fieldid: FieldId, callback: (field: Opt<Field>) => void): void;
+ public static GetField(fieldid: FieldId, callback?: (field: Opt<Field>) => void): Promise<Opt<Field>> | void {
+ let fn = (cb: (field: Opt<Field>) => void) => {
+
+ let cached = this.ClientFieldsCached.get(fieldid);
+ if (!cached) {
+ this.ClientFieldsCached.set(fieldid, FieldWaiting);
+ SocketStub.SEND_FIELD_REQUEST(fieldid, action((field: Field | undefined) => {
+ let cached = this.ClientFieldsCached.get(fieldid);
+ if (cached != FieldWaiting)
+ cb(cached);
+ else {
+ if (field) {
+ this.ClientFieldsCached.set(fieldid, field);
+ } else {
+ this.ClientFieldsCached.delete(fieldid)
+ }
+ cb(field)
}
- callback(field)
- }
- }));
- } else if (cached != FieldWaiting) {
- setTimeout(() => callback(cached as Field), 0);
+ }));
+ } else if (cached != FieldWaiting) {
+ setTimeout(() => cb(cached as Field), 0);
+ } else {
+ reaction(() => {
+ return this.ClientFieldsCached.get(fieldid);
+ }, (field, reaction) => {
+ if (field !== "<Waiting>") {
+ reaction.dispose()
+ cb(field)
+ }
+ })
+ }
+ }
+ if (callback) {
+ fn(callback);
} else {
- reaction(() => {
- return this.ClientFieldsCached.get(fieldid);
- }, (field, reaction) => {
- if (field !== "<Waiting>") {
- reaction.dispose()
- callback(field)
- }
- })
+ return new Promise<Opt<Field>>(res => fn(res));
}
- return cached;
}
public static GetFields(fieldIds: FieldId[], callback: (fields: { [id: string]: Field }) => any) {
@@ -71,7 +79,7 @@ export class Server {
}
}
reaction(() => {
- return waitingFieldIds.map(this.ClientFieldsCached.get);
+ return waitingFieldIds.map(id => this.ClientFieldsCached.get(id));
}, (cachedFields, reaction) => {
if (!cachedFields.some(field => !field || field === FieldWaiting)) {
reaction.dispose();
diff --git a/src/client/SocketStub.ts b/src/client/SocketStub.ts
index a0b89b7c9..27528c4c3 100644
--- a/src/client/SocketStub.ts
+++ b/src/client/SocketStub.ts
@@ -35,16 +35,23 @@ export class SocketStub {
Utils.Emit(Server.Socket, MessageStore.AddDocument, new DocumentTransfer(document.ToJson()))
}
- public static SEND_FIELD_REQUEST(fieldid: FieldId, callback: (field: Opt<Field>) => void) {
- if (fieldid) {
+ public static SEND_FIELD_REQUEST(fieldid: FieldId): Promise<Opt<Field>>;
+ public static SEND_FIELD_REQUEST(fieldid: FieldId, callback: (field: Opt<Field>) => void): void;
+ public static SEND_FIELD_REQUEST(fieldid: FieldId, callback?: (field: Opt<Field>) => void): Promise<Opt<Field>> | void {
+ let fn = function (cb: (field: Opt<Field>) => void) {
Utils.EmitCallback(Server.Socket, MessageStore.GetField, fieldid, (field: any) => {
if (field) {
- ServerUtils.FromJson(field).init(callback);
+ ServerUtils.FromJson(field).init(cb);
} else {
- callback(undefined);
+ cb(undefined);
}
})
}
+ if (callback) {
+ fn(callback);
+ } else {
+ return new Promise(res => fn(res))
+ }
}
public static SEND_FIELDS_REQUEST(fieldIds: FieldId[], callback: (fields: { [key: string]: Field }) => any) {
diff --git a/src/fields/Document.ts b/src/fields/Document.ts
index b6439364a..66d3d3aef 100644
--- a/src/fields/Document.ts
+++ b/src/fields/Document.ts
@@ -124,22 +124,31 @@ export class Document extends Field {
* Note: The callback will not be called if there is no associated field.
* @returns `true` if the field exists on the document and `callback` will be called, and `false` otherwise
*/
- GetAsync(key: Key, callback: (field: Field) => void): boolean {
+ GetAsync(key: Key, callback: (field: Opt<Field>) => void): void {
//TODO: This currently doesn't deal with prototypes
let field = this.fields.get(key.Id);
if (field && field.field) {
callback(field.field);
} else if (this._proxies.has(key.Id)) {
Server.GetDocumentField(this, key, callback);
- return true;
+ } else {
+ callback(undefined);
}
- return false;
}
- GetTAsync<T extends Field>(key: Key, ctor: { new(): T }, callback: (field: Opt<T>) => void): boolean {
- return this.GetAsync(key, (field) => {
- callback(Cast(field, ctor));
- })
+ GetTAsync<T extends Field>(key: Key, ctor: { new(): T }): Promise<Opt<T>>;
+ GetTAsync<T extends Field>(key: Key, ctor: { new(): T }, callback: (field: Opt<T>) => void): void;
+ GetTAsync<T extends Field>(key: Key, ctor: { new(): T }, callback?: (field: Opt<T>) => void): Promise<Opt<T>> | void {
+ let fn = (cb: (field: Opt<T>) => void) => {
+ return this.GetAsync(key, (field) => {
+ cb(Cast(field, ctor));
+ });
+ }
+ if (callback) {
+ fn(callback);
+ } else {
+ return new Promise(res => fn(res));
+ }
}
/**
@@ -215,13 +224,6 @@ export class Document extends Field {
}
@action
- SetOnPrototype(key: Key, field: Field | undefined): void {
- this.GetAsync(KeyStore.Prototype, (f: Field) => {
- (f as Document).Set(key, field)
- })
- }
-
- @action
Set(key: Key, field: Field | undefined, setOnPrototype = false): void {
let old = this.fields.get(key.Id);
let oldField = old ? old.field : undefined;
@@ -249,15 +251,21 @@ export class Document extends Field {
}
@action
+ SetOnPrototype(key: Key, field: Field | undefined): void {
+ this.GetTAsync(KeyStore.Prototype, Document, (f: Opt<Document>) => {
+ f && f.Set(key, field)
+ })
+ }
+
+ @action
SetDataOnPrototype<T, U extends Field & { Data: T }>(key: Key, value: T, ctor: { new(): U }, replaceWrongType = true) {
- this.GetAsync(KeyStore.Prototype, (f: Field) => {
- (f as Document).SetData(key, value, ctor)
+ this.GetTAsync(KeyStore.Prototype, Document, (f: Opt<Document>) => {
+ f && f.SetData(key, value, ctor)
})
}
@action
SetData<T, U extends Field & { Data: T }>(key: Key, value: T, ctor: { new(): U }, replaceWrongType = true) {
-
let field = this.Get(key, true);
if (field instanceof ctor) {
field.Data = value;
@@ -294,8 +302,8 @@ export class Document extends Field {
CreateAlias(id?: string): Document {
let alias = new Document(id)
- this.GetAsync(KeyStore.Prototype, (f: Field) => {
- alias.Set(KeyStore.Prototype, f)
+ this.GetTAsync(KeyStore.Prototype, Document, (f: Opt<Document>) => {
+ f && alias.Set(KeyStore.Prototype, f)
})
return alias