From 761b2c6e42e300b70ad2a43a682333adf9c37a22 Mon Sep 17 00:00:00 2001 From: David Banham Date: Wed, 8 Mar 2017 13:57:37 +1100 Subject: [PATCH] Switch application.js to native Promises --- lib/application.js | 334 ++++++++++++++++++++++----------------------- 1 file changed, 163 insertions(+), 171 deletions(-) diff --git a/lib/application.js b/lib/application.js index a183d745..8d157e24 100644 --- a/lib/application.js +++ b/lib/application.js @@ -2,7 +2,6 @@ var _ = require('lodash'), logger = require('./logger'), OAuth = require('./oauth/oauth').OAuth, OAuthEcho = require('./oauth/oauth').OAuthEcho, - p = require('./misc/promise'), fs = require('fs'), extend = require('./misc/extend'), dateformat = require('dateformat'), @@ -98,104 +97,96 @@ _.extend(Application.prototype, { options = {}; } options = options || {}; - var deferred = p.defer(); - var params = {}; - if (options.summarizeErrors === false) - params.summarizeErrors = false; - - //Added to support more than 2dp being added. - if (options.unitdp) - params.unitdp = options.unitdp; - - var endPointUrl = options.api === 'payroll' ? this.options.payrollAPIEndPointUrl : this.options.coreAPIEndPointUrl; - var url = this.options.baseUrl + endPointUrl + path; - if (!_.isEmpty(params)) - url += '?' + querystring.stringify(params); - - this.oa[method](url, this.options.accessToken, this.options.accessSecret, { xml: body }, function(err, data, res) { - - if (err && data && data.indexOf('oauth_problem') >= 0) { - var errObj = new Error(method.toUpperCase() + ' call failed with: ' + err.statusCode); - errObj.data = qs.parse(data); - deferred.reject(errObj); - callback && callback(errObj); - return; - } + return new Promise(function(resolve, reject) { + var params = {}; + if (options.summarizeErrors === false) + params.summarizeErrors = false; - self.xml2js(data) - .then(function(obj) { - if (err) { - var exception = ""; - if (obj.ApiException) - exception = obj.ApiException; - else if (obj.Response.ErrorNumber) - exception = obj.Response; - var errObj = new Error(method.toUpperCase() + ' call failed with: ' + err.statusCode + ' and exception: ' + JSON.stringify(exception, null, 2)); - deferred.reject(errObj); - callback && callback(errObj); - } else { - var ret = { response: obj.Response, res: res }; - if (options.entityConstructor) { - ret.entities = self.convertEntities(obj.Response, options); + //Added to support more than 2dp being added. + if (options.unitdp) + params.unitdp = options.unitdp; + + var endPointUrl = options.api === 'payroll' ? self.options.payrollAPIEndPointUrl : self.options.coreAPIEndPointUrl; + var url = self.options.baseUrl + endPointUrl + path; + if (!_.isEmpty(params)) + url += '?' + querystring.stringify(params); + + self.oa[method](url, self.options.accessToken, self.options.accessSecret, { xml: body }, function(err, data, res) { + + if (err && data && data.indexOf('oauth_problem') >= 0) { + var errObj = new Error(method.toUpperCase() + ' call failed with: ' + err.statusCode); + errObj.data = qs.parse(data); + reject(errObj); + callback && callback(errObj); + return; + } + + self.xml2js(data) + .then(function(obj) { + if (err) { + var exception = ""; + if (obj.ApiException) + exception = obj.ApiException; + else if (obj.Response.ErrorNumber) + exception = obj.Response; + var errObj = new Error(method.toUpperCase() + ' call failed with: ' + err.statusCode + ' and exception: ' + JSON.stringify(exception, null, 2)); + reject(errObj); + callback && callback(errObj); + } else { + var ret = { response: obj.Response, res: res }; + if (options.entityConstructor) { + ret.entities = self.convertEntities(obj.Response, options); + } + resolve(ret); + callback && callback(null, obj, res, ret.entities); } - deferred.resolve(ret); - callback && callback(null, obj, res, ret.entities); - } - }) - .catch(function(err) { - logger.error(err); - throw err; - }) + }) + .catch(function(err) { + logger.error(err); + throw err; + }) + }); }); - return deferred.promise; }, delete: function(path, options, callback) { var self = this; options = options || {}; - var deferred, promise; - deferred = p.defer(); - promise = deferred.promise; - - deleteResource(); - - return promise; - - function deleteResource() { + return new Promise(function(resolve, reject) { var endPointUrl = options.api === 'payroll' ? self.options.payrollAPIEndPointUrl : self.options.coreAPIEndPointUrl; var url = self.options.baseUrl + endPointUrl + path; self.oa.delete(url, self.options.accessToken, self.options.accessSecret, function(err, data, res) { if (options.stream && !err) { // Already done - return deferred.resolve(); + return resolve(); } if (err && data && data.indexOf('oauth_problem') >= 0) { var errObj = new Error('DELETE call failed with: ' + err.statusCode); errObj.data = qs.parse(data); - deferred.reject(errObj); + reject(errObj); callback && callback(errObj); return; } if (err) { var errObj = new Error('DELETE call failed with: ' + err.statusCode + ' and message: ' + err.data); - deferred.reject(errObj); + reject(errObj); callback && callback(errObj); return; } //Some delete operations don't return any content (e.g. HTTP204) so simply resolve the promise if (!data || data === "") { - return deferred.resolve(); + return resolve(); } self.xml2js(data) .then(function(obj) { var ret = { response: obj.Response, res: res }; - deferred.resolve(ret); + resolve(ret); callback && callback(null, obj, res); }) .catch(function(err) { @@ -203,110 +194,105 @@ _.extend(Application.prototype, { throw err; }) }, { stream: options.stream }); - - } + }); }, get: function(path, options, callback) { var self = this; options = options || {}; - var deferred, promise; - - // modifiedAfter - delete self.oa._headers['If-Modified-Since']; - if (options.modifiedAfter) - this.oa._headers['If-Modified-Since'] = dateformat(options.modifiedAfter, 'yyyy-mm-dd"T"hh:MM:ss'); - if (options.format) - this.oa._headers['Accept'] = 'application/' + options.format; - deferred = p.defer(); - promise = deferred.promise; + return new Promise(function(resolve, reject) { + // modifiedAfter + delete self.oa._headers['If-Modified-Since']; + if (options.modifiedAfter) + self.oa._headers['If-Modified-Since'] = dateformat(options.modifiedAfter, 'yyyy-mm-dd"T"hh:MM:ss'); + if (options.format) + self.oa._headers['Accept'] = 'application/' + options.format; - if (options.pager) - getResource(options.pager.start || 1) - else - getResource(); - - return promise; - - function getResource(offset) { - var endPointUrl = options.api === 'payroll' ? self.options.payrollAPIEndPointUrl : self.options.coreAPIEndPointUrl; - var url = self.options.baseUrl + endPointUrl + path; - var params = {}; - if (offset) { - params[options.pager.paramName || 'page'] = offset; - if (options.other) { - _.each(options.other, function(value, key) { - if (!_.isUndefined(value)) - params[key] = value; - }) + if (options.pager) + getResource(options.pager.start || 1) + else + getResource(); + + function getResource(offset) { + var endPointUrl = options.api === 'payroll' ? self.options.payrollAPIEndPointUrl : self.options.coreAPIEndPointUrl; + var url = self.options.baseUrl + endPointUrl + path; + var params = {}; + if (offset) { + params[options.pager.paramName || 'page'] = offset; + if (options.other) { + _.each(options.other, function(value, key) { + if (!_.isUndefined(value)) + params[key] = value; + }) + } } - } - /* - Added for where clause support on the GET requests. - */ - if (options.where) { - params['Where'] = options.where; - } - - if (!_.isEmpty(params)) { - url += '?' + querystring.stringify(params); - } - - self.oa.get(url, self.options.accessToken, self.options.accessSecret, function(err, data, res) { - if (options.stream && !err) { - // Already done - return deferred.resolve(); - } - if (err && data) { - var dataParts; - if (_.isObject(data)) - dataParts = qs.parse(data); - else - dataParts = data; - - var errObj = new Error('GET call failed with: ' + err.statusCode); - errObj.data = dataParts; - deferred.reject(errObj); - callback && callback(errObj); - return; + /* + Added for where clause support on the GET requests. + */ + if (options.where) { + params['Where'] = options.where; } - self.xml2js(data) - .then(function(obj) { - var ret = { response: obj.Response, res: res }; - if (err) { - var errObj = new Error('GET call failed with: ' + err.statusCode + ' and exception: ' + JSON.stringify(obj.ApiException, null, 2)); - deferred.reject(errObj); - callback && callback(errObj); - return; - } - - if (options.pager && options.pager.callback) { - options.pager.callback(err, ret, function(err, result) { - result = _.defaults({}, result, { recordCount: 0, stop: false }); - if (!result.stop) - getResource(result.nextOffset || ++offset); - else - done(); - }) - return; - } + if (!_.isEmpty(params)) { + url += '?' + querystring.stringify(params); + } - done(); + self.oa.get(url, self.options.accessToken, self.options.accessSecret, function(err, data, res) { + if (options.stream && !err) { + // Already done + return resolve(); + } + if (err && data) { + var dataParts; + if (_.isObject(data)) + dataParts = qs.parse(data); + else + dataParts = data; + + var errObj = new Error('GET call failed with: ' + err.statusCode); + errObj.data = dataParts; + reject(errObj); + callback && callback(errObj); + return; + } - function done() { - deferred.resolve(ret); - callback && callback(null, obj, res); - } - }) - .catch(function(err) { - logger.error(err); - throw err; - }) - }, { stream: options.stream }); + self.xml2js(data) + .then(function(obj) { + var ret = { response: obj.Response, res: res }; + if (err) { + var errObj = new Error('GET call failed with: ' + err.statusCode + ' and exception: ' + JSON.stringify(obj.ApiException, null, 2)); + reject(errObj); + callback && callback(errObj); + return; + } + + if (options.pager && options.pager.callback) { + options.pager.callback(err, ret, function(err, result) { + result = _.defaults({}, result, { recordCount: 0, stop: false }); + if (!result.stop) + getResource(result.nextOffset || ++offset); + else + done(); + }) + return; + } + + done(); + + function done() { + resolve(ret); + callback && callback(null, obj, res); + } + }) + .catch(function(err) { + logger.error(err); + throw err; + }) + }, { stream: options.stream }); - } + }; + }); }, asArray: function(obj) { if (_.isArray(obj)) @@ -377,8 +363,6 @@ _.extend(Application.prototype, { var self = this; var clonedOptions = _.clone(options || {}); - var deferred = p.defer(); - var callerPagerCallback; if (clonedOptions.pager) { callerPagerCallback = clonedOptions.pager.callback; @@ -423,7 +407,12 @@ _.extend(Application.prototype, { }, xml2js: function(xml) { var parser = new xml2js.Parser({ explicitArray: false }); - return p.nbind(parser.parseString, parser)(xml); + return new Promise(function(resolve, reject) { + parser.parseString(xml, function(err, result) { + if (err) return reject(err); + resolve(result); + }); + }); }, js2xml: function(obj, rootName) { var builder = new xml2js.Builder({ rootName: rootName, headless: true }); @@ -507,27 +496,30 @@ var RequireAuthorizationApplication = Application.extend({ } extras = extras || {}; - var deferred = p.defer(); - this.oa.getOAuthRequestToken(extras, function(err, token, secret, results) { - if (err) - deferred.reject(err); - else - deferred.resolve({ token: token, secret: secret, results: results }); - callback && callback.apply(callback, arguments); + var self = this; + + return new Promise(function(resolve, reject) { + self.oa.getOAuthRequestToken(extras, function(err, token, secret, results) { + if (err) + reject(err); + else + resolve({ token: token, secret: secret, results: results }); + callback && callback.apply(callback, arguments); + }); }); - return deferred.promise; }, getAccessToken: function(token, secret, verifier, callback, options) { - var deferred = p.defer(); - this.oa.getOAuthAccessToken(token, secret, verifier, - function(err, token, secret, results) { + var self = this; + + return new Promise(function(resolve, reject) { + self.oa.getOAuthAccessToken(token, secret, verifier, function(err, token, secret, results) { if (err) - deferred.reject(err); + reject(err); else - deferred.resolve({ token: token, secret: secret, results: results }); + resolve({ token: token, secret: secret, results: results }); callback && callback.apply(callback, arguments); }) - return deferred.promise; + }); }, buildAuthorizeUrl: function(requestToken, other) { var q = _.extend({}, { oauth_token: requestToken }, other); @@ -607,4 +599,4 @@ var PartnerApplication = RequireAuthorizationApplication.extend({ module.exports.PrivateApplication = PrivateApplication; module.exports.PublicApplication = PublicApplication; module.exports.PartnerApplication = PartnerApplication; -module.exports.Application = Application; \ No newline at end of file +module.exports.Application = Application;