From 6d013fe15253874134f077c1157f46615cd4aade Mon Sep 17 00:00:00 2001 From: Andrew Imm Date: Mon, 4 Jan 2016 23:36:04 -0800 Subject: [PATCH 1/3] Allow ES6-style Promise construction --- src/ParsePromise.js | 6 +++++- src/__tests__/ParsePromise-test.js | 34 +++++++++++++++++++++++++++++- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/src/ParsePromise.js b/src/ParsePromise.js index a50073029..173323eff 100644 --- a/src/ParsePromise.js +++ b/src/ParsePromise.js @@ -26,11 +26,15 @@ var isPromisesAPlusCompliant = true; * @constructor */ export default class ParsePromise { - constructor() { + constructor(closure) { this._resolved = false; this._rejected = false; this._resolvedCallbacks = []; this._rejectedCallbacks = []; + + if (typeof closure === 'function') { + closure(this.resolve.bind(this), this.reject.bind(this)); + } } /** diff --git a/src/__tests__/ParsePromise-test.js b/src/__tests__/ParsePromise-test.js index 714d00596..173fd7bdb 100644 --- a/src/__tests__/ParsePromise-test.js +++ b/src/__tests__/ParsePromise-test.js @@ -430,5 +430,37 @@ describe('Promise', () => { expect(ParsePromise.is({})).toBe(false); expect(ParsePromise.is(ParsePromise.as())).toBe(true); expect(ParsePromise.is(ParsePromise.error())).toBe(true); - }) + }); + + it('can be constructed in ES6 style and resolved', asyncHelper((done) => { + new ParsePromise((resolve, reject) => { + resolve('abc'); + }).then((result) => { + expect(result).toBe('abc'); + + return new ParsePromise((resolve, reject) => { + resolve('def'); + }); + }).then((result) => { + expect(result).toBe('def'); + done(); + }); + })); + + it('can be constructed in ES6 style and rejected', asyncHelper((done) => { + new ParsePromise((resolve, reject) => { + reject('err'); + }).then(() => { + // Should not be reached + }, (error) => { + expect(error).toBe('err'); + + return new ParsePromise((resolve, reject) => { + reject('err2'); + }); + }).then(null, (error) => { + expect(error).toBe('err2'); + done(); + }); + })); }); From 4a09e26adcce44cdb71dab1166c09937c7cc3d96 Mon Sep 17 00:00:00 2001 From: Andrew Imm Date: Tue, 5 Jan 2016 00:31:39 -0800 Subject: [PATCH 2/3] Add ES6 shortcut constructors --- src/ParsePromise.js | 33 ++++++++++++++++++++++++++++++ src/__tests__/ParsePromise-test.js | 20 ++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/src/ParsePromise.js b/src/ParsePromise.js index 173323eff..2a55130cd 100644 --- a/src/ParsePromise.js +++ b/src/ParsePromise.js @@ -305,6 +305,26 @@ export default class ParsePromise { return promise; } + /** + * Returns a new promise that is resolved with a given value. + * If that value is a thenable Promise (has a .then() prototype + * method), the new promise will be chained to the end of the + * value. + * @method resolve + * @param value The value to resolve the promise with + * @static + * @return {Parse.Promise} the new promise. + */ + static resolve(value) { + return new ParsePromise((resolve, reject) => { + if (ParsePromise.is(value)) { + value.then(resolve, reject); + } else { + resolve(value); + } + }); + } + /** * Returns a new promise that is rejected with a given error. * @method error @@ -318,6 +338,19 @@ export default class ParsePromise { return promise; } + /** + * Returns a new promise that is rejected with a given error. + * This is an alias for Parse.Promise.error, for compliance with + * the ES6 implementation. + * @method reject + * @param error The error to reject the promise with + * @static + * @return {Parse.Promise} the new promise. + */ + static reject(...errors) { + return ParsePromise.error.apply(null, errors); + } + /** * Returns a new promise that is fulfilled when all of the input promises * are resolved. If any promise in the list fails, then the returned promise diff --git a/src/__tests__/ParsePromise-test.js b/src/__tests__/ParsePromise-test.js index 173fd7bdb..a6667c6f3 100644 --- a/src/__tests__/ParsePromise-test.js +++ b/src/__tests__/ParsePromise-test.js @@ -433,6 +433,8 @@ describe('Promise', () => { }); it('can be constructed in ES6 style and resolved', asyncHelper((done) => { + expect(ParsePromise.length).toBe(1); // constructor arguments + new ParsePromise((resolve, reject) => { resolve('abc'); }).then((result) => { @@ -463,4 +465,22 @@ describe('Promise', () => { done(); }); })); + + it('can be initially resolved, ES6 style', asyncHelper((done) => { + ParsePromise.resolve('abc').then((result) => { + expect(result).toBe('abc'); + + return ParsePromise.resolve(ParsePromise.as('def')); + }).then((result) => { + expect(result).toBe('def'); + done(); + }); + })); + + it('can be initially rejected, ES6 style', asyncHelper((done) => { + ParsePromise.reject('err').then(null, (error) => { + expect(error).toBe('err'); + done(); + }); + })); }); From 699561ce40644b9b06f9e30d55d832406fcd418c Mon Sep 17 00:00:00 2001 From: Andrew Imm Date: Tue, 5 Jan 2016 10:37:01 -0800 Subject: [PATCH 3/3] Rename closure to executor --- src/ParsePromise.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ParsePromise.js b/src/ParsePromise.js index 2a55130cd..b1b300464 100644 --- a/src/ParsePromise.js +++ b/src/ParsePromise.js @@ -26,14 +26,14 @@ var isPromisesAPlusCompliant = true; * @constructor */ export default class ParsePromise { - constructor(closure) { + constructor(executor) { this._resolved = false; this._rejected = false; this._resolvedCallbacks = []; this._rejectedCallbacks = []; - if (typeof closure === 'function') { - closure(this.resolve.bind(this), this.reject.bind(this)); + if (typeof executor === 'function') { + executor(this.resolve.bind(this), this.reject.bind(this)); } }