diff options
author | Tyler Schicke <tyler_schicke@brown.edu> | 2019-03-20 05:04:01 -0400 |
---|---|---|
committer | Tyler Schicke <tyler_schicke@brown.edu> | 2019-03-20 05:04:01 -0400 |
commit | 6473fdcbc01fecfa5bc8dc46cdcd7841c1ef35ae (patch) | |
tree | 714acad00a6ea8a0ffa4618558ce16b49be13880 /src | |
parent | e418b10b4e515c6ebbe0b9be64e7bfd451ddd11f (diff) |
Started adding support for promises
Diffstat (limited to 'src')
-rw-r--r-- | src/Utils.ts | 12 | ||||
-rw-r--r-- | src/client/Server.ts | 66 | ||||
-rw-r--r-- | src/client/SocketStub.ts | 15 | ||||
-rw-r--r-- | src/fields/Document.ts | 46 |
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 |