I have a Node.js typescript code where I am passing Google methods as a parameter to another method which in turn calls Google method. Following is the code which calls the methods:
public static async GCloudAsync (method: (params: any, callback: any) => void, params: any): Promise<any> {
const auth = await google.auth.getClient({
scopes: [ 'https://www.googleapis.com/auth/cloud-platform' ]
});
Object.assign(params,{ auth });
return new Promise<any>((resolve, reject) => {
method(params, (error: any, result: any) => {
if (error) {
if (error.code !== 404 && error.code !== 500) {
return;
}
return reject(error);
}
return resolve(result.data);
});
});
}
The above function is being called like this:
const { google } = require('googleapis');
const projectInfo = await Google.GCloudAsync(google.compute('beta').projects.get, {
project: <GoogleProjectId>
});
This code works perfectly fine till googleapis library version 38.0.0. But when I tried to upgrade it to 40.0.0, I am facing following error:
(node:1836) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'context' of undefined
at get (node_modules\googleapis\build\src\apis\compute\beta.js:9092:31)
at Promise (build\app\classes\google\Google.js:61:17)
at new Promise ()
at Function.(build\app\classes\google\Google.js:60:20)
at Generator.next ()
at fulfilled (build\app\classes\google\Google.js:6:58)
at process._tickCallback (internal/process/next_tick.js:68:7)
(node:1836) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 2)
(node:1836) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
I am not sure what got changed in 39.0.0 or 40.0.0, but somehow I am not able to pass methods to be called by another method. Without passing it works perfectly fine
Apologies - I'm having a bit of a hard time parsing the example code here :) It looks like you're doing some gymnastics to try supporting promises... which are supported natively!
Can you try something like this?
import {google} from 'googleapis';
const compute = google.compute('v1');
async function doStuff() {
const auth = await google.auth.getClient({
scopes: [ 'https://www.googleapis.com/auth/cloud-platform' ]
});
const res = await compute.projects.get({
auth,
project: yourProjectId
});
console.log(res.data);
}
doStuff().catch(console.error);
similar situation here, I pass the promise to run as a parameter. What has changed?
Can you share an example of the code you're using?
Greetings! I'm going to go ahead and close this out for now. If you're still running into issues ... please do let us know!
I was getting this error and it turned out to be because i was passing around functions references like androidpublisher.purchases.subscriptions.get. I was upgrading my package from a _much_ older version where this was working fine. To fix, I bound the functions like androidpublisher.purchases.subscriptions.get.bind(androidpublisher.purchases.subscriptions)
@nickcarenza this is exactly what the problem is. With version <= 38.0.0, passing around the functions work, but after version 38.0.0, passing the function to another function doesn't work. I don't understand what has changed.
@JustinBeckwith The example you gave will work perfectly. The thing which will not work looks something like below:
import {google} from 'googleapis';
const compute = google.compute('v1');
async function doStuff() {
const auth = await google.auth.getClient({
scopes: [ 'https://www.googleapis.com/auth/cloud-platform' ]
});
const res = await runGoogleFunction(compute.projects.get);
}
doStuff().catch(console.error);
runGoogleFunction(func) {
return func({
auth,
project: yourProjectId
});
}
Im having the same issue thrown while running some older code from sfdx -mdapi plugin code:
class Changeset extends command_1.SfdxCommand {
async run() {
let defaultApiVersion = await this.org.retrieveMaxApiVersion();
let ignorecomments = this.flags.ignorecomments || false;
let targetusername = this.flags.targetusername;
let sourceusername = this.flags.sourceusername;
let excludepath = this.flags.excludepath || null;
let revisionfrom = this.flags.revisionfrom || null;
let revisionto = this.flags.revisionto || null;
let apiversion = this.flags.apiversion || defaultApiVersion;
if (sourceusername === undefined) {
throw new core_1.SfdxError(messages.getMessage('errorSourceusernameRequired'));
} // end if
else if ((revisionfrom === null && revisionto !== null) || (revisionfrom !== null && revisionto === null)) {
throw new core_1.SfdxError(messages.getMessage('errorBothRevisionsRequired'));
} // end if
this.ux.log("-----------------------------");
this.ux.log("sfdx ext:mdapi:changeset");
this.ux.log("-----------------------------");
this.ux.log("sourceusername : " + sourceusername);
this.ux.log("targetusername : " + targetusername);
this.ux.log("apiversion : " + apiversion);
this.ux.log("ignorecomments : " + ignorecomments);
this.ux.log("excludepath : " + excludepath);
this.ux.log("revisionfrom : " + revisionfrom);
this.ux.log("revisionto : " + revisionto);
this.ux.log("-----------------------------");
let util = new mdapi_changeset_utility_1.MdapiChangesetUtility(this.org, this.ux, sourceusername, targetusername, apiversion, ignorecomments, excludepath, revisionfrom, revisionto);
return new Promise((resolve, reject) => {
util.process().then(() => {
this.ux.log('success.');
resolve({ "status": 'success' });
}, (error) => {
this.ux.error(error);
reject({
"status": 'error',
"error": error
});
});
});
} // end method
} // end class
Changeset.description = messages.getMessage('commandDescription');
Changeset.examples = [
How can I make the relevant code changes to resolve:
(node:18568) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:18568) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
this is the actual class :
compareProfileObjectPermissions(leftItem, rightItem) {
// check if items exist on right but not on left.
// set right item to remove and inject into left file to delete in right.
// extract left
let leftJsonObject = mdapi_common_1.MdapiCommon.xmlFileToJson(leftItem.filePath);
let leftProfile = leftJsonObject[mdapi_config_1.MdapiConfig.Profile];
let leftObjectPermissions = mdapi_common_1.MdapiCommon.objectToArray(leftProfile.objectPermissions);
let leftUserPermissions = mdapi_common_1.MdapiCommon.objectToArray(leftProfile.userPermissions);
let leftTabVisibilities = mdapi_common_1.MdapiCommon.objectToArray(leftProfile.tabVisibilities);
let leftFieldPermissions = mdapi_common_1.MdapiCommon.objectToArray(leftProfile.fieldPermissions);
let leftCustomPermissions = mdapi_common_1.MdapiCommon.objectToArray(leftProfile.customPermissions);
let leftClassAccesses = mdapi_common_1.MdapiCommon.objectToArray(leftProfile.classAccesses);
let leftApplicationVisibilities = mdapi_common_1.MdapiCommon.objectToArray(leftProfile.applicationVisibilities);
let leftPageAccesses = mdapi_common_1.MdapiCommon.objectToArray(leftProfile.pageAccesses);
let leftRecordTypeVisibilities = mdapi_common_1.MdapiCommon.objectToArray(leftProfile.recordTypeVisibilities);
// extract right
let rightJsonObject = mdapi_common_1.MdapiCommon.xmlFileToJson(rightItem.filePath);
let rightProfile = rightJsonObject[mdapi_config_1.MdapiConfig.Profile];
let rightObjectPermissions = mdapi_common_1.MdapiCommon.objectToArray(rightProfile.objectPermissions);
let rightUserPermissions = mdapi_common_1.MdapiCommon.objectToArray(rightProfile.userPermissions);
let rightTabVisibilities = mdapi_common_1.MdapiCommon.objectToArray(rightProfile.tabVisibilities);
let rightFieldPermissions = mdapi_common_1.MdapiCommon.objectToArray(rightProfile.fieldPermissions);
let rightCustomPermissions = mdapi_common_1.MdapiCommon.objectToArray(rightProfile.customPermissions);
let rightClassAccesses = mdapi_common_1.MdapiCommon.objectToArray(rightProfile.classAccesses);
let rightApplicationVisibilities = mdapi_common_1.MdapiCommon.objectToArray(rightProfile.applicationVisibilities);
let rightPageAccesses = mdapi_common_1.MdapiCommon.objectToArray(rightProfile.pageAccesses);
let rightRecordTypeVisibilities = mdapi_common_1.MdapiCommon.objectToArray(rightProfile.recordTypeVisibilities);
// process object permissions
for (let right = 0; right < rightObjectPermissions.length; right++) {
let found = false;
let rightObjectPermission = rightObjectPermissions[right];
for (let left = 0; left < leftObjectPermissions.length; left++) {
let leftObjectPermission = leftObjectPermissions[left];
if (rightObjectPermission.object._text === leftObjectPermission.object._text) {
found = true;
break;
} // end if
} // end for left
// handle if not found
if (!found) {
rightObjectPermission.allowCreate._text = 'false';
rightObjectPermission.allowDelete._text = 'false';
rightObjectPermission.allowEdit._text = 'false';
rightObjectPermission.allowRead._text = 'false';
rightObjectPermission.modifyAllRecords._text = 'false';
rightObjectPermission.viewAllRecords._text = 'false';
leftObjectPermissions.push(rightObjectPermission);
} // end if
} // end for right
// process user permissions
for (let right = 0; right < rightUserPermissions.length; right++) {
let found = false;
let rightUserPermission = rightUserPermissions[right];
for (let left = 0; left < leftUserPermissions.length; left++) {
let leftUserPermission = leftUserPermissions[left];
if (rightUserPermission.name._text === leftUserPermission.name._text) {
found = true;
break;
} // end if
} // end for left
// handle if not found
if (!found) {
rightUserPermission.enabled._text = 'false';
leftUserPermissions.push(rightUserPermission);
} // end if
} // end for right
// process tab visibilities
for (let right = 0; right < rightTabVisibilities.length; right++) {
let found = false;
let rightTabVisibility = rightTabVisibilities[right];
for (let left = 0; left < leftTabVisibilities.length; left++) {
let leftTabVisibility = leftTabVisibilities[left];
if (rightTabVisibility.tab._text === leftTabVisibility.tab._text) {
found = true;
break;
} // end if
} // end for left
// handle if not found
if (!found) {
rightTabVisibility.visibility._text = 'Hidden';
leftTabVisibilities.push(rightTabVisibility);
} // end if
} // end for right
// process field permissions
for (let right = 0; right < rightFieldPermissions.length; right++) {
let found = false;
let rightFieldPermission = rightFieldPermissions[right];
for (let left = 0; left < leftFieldPermissions.length; left++) {
let leftFieldPermission = leftFieldPermissions[left];
if (rightFieldPermission.field._text === leftFieldPermission.field._text) {
found = true;
break;
} // end if
} // end for left
// handle if not found
if (!found) {
rightFieldPermission.editable._text = 'false';
rightFieldPermission.readable._text = 'false';
leftFieldPermissions.push(rightFieldPermission);
} // end if
} // end for right
// process custom permissions
for (let right = 0; right < rightCustomPermissions.length; right++) {
let found = false;
let rightCustomPermission = rightCustomPermissions[right];
for (let left = 0; left < leftCustomPermissions.length; left++) {
let leftCustomPermission = leftCustomPermissions[left];
if (rightCustomPermission.name._text === leftCustomPermission.name._text) {
found = true;
break;
} // end if
} // end for left
// handle if not found
if (!found) {
rightCustomPermission.enabled._text = 'false';
leftCustomPermissions.push(rightCustomPermission);
} // end if
} // end for right
// process class accesses
for (let right = 0; right < leftClassAccesses.length; right++) {
let found = false;
let rightClassAccess = rightClassAccesses[right];
for (let left = 0; left < leftClassAccesses.length; left++) {
let leftClassAccess = leftClassAccesses[left];
if (rightClassAccess.apexClass._text === leftClassAccess.apexClass._text) {
found = true;
break;
} // end if
} // end for left
// handle if not found
if (!found) {
rightClassAccess.enabled._text = 'false';
leftClassAccesses.push(rightClassAccess);
} // end if
} // end for right
// process application visibilities
for (let right = 0; right < rightApplicationVisibilities.length; right++) {
let found = false;
let rightApplicationVisibility = rightApplicationVisibilities[right];
for (let left = 0; left < leftApplicationVisibilities.length; left++) {
let leftApplicationVisibility = leftApplicationVisibilities[left];
if (rightApplicationVisibility.application._text === leftApplicationVisibility.application._text) {
found = true;
break;
} // end if
} // end for left
// handle if not found
if (!found) {
rightApplicationVisibility.default._text = 'false';
rightApplicationVisibility.visible._text = 'false';
leftApplicationVisibilities.push(rightApplicationVisibility);
} // end if
} // end for right
// process page accesses
for (let right = 0; right < leftPageAccesses.length; right++) {
let found = false;
let rightPageAccess = rightPageAccesses[right];
for (let left = 0; left < leftPageAccesses.length; left++) {
let leftPageAccess = leftPageAccesses[left];
if (rightPageAccess.apexPage._text === leftPageAccess.apexPage._text) {
found = true;
break;
} // end if
} // end for left
// handle if not found
if (!found) {
rightPageAccess.enabled._text = 'false';
leftPageAccesses.push(rightPageAccess);
} // end if
} // end for right
// process record type visibilities
for (let right = 0; right < rightRecordTypeVisibilities.length; right++) {
let found = false;
let rightRecordTypeVisibility = rightRecordTypeVisibilities[right];
for (let left = 0; left < leftRecordTypeVisibilities.length; left++) {
let leftRecordTypeVisibility = leftRecordTypeVisibilities[left];
if (rightRecordTypeVisibility.recordType._text === leftRecordTypeVisibility.recordType._text) {
found = true;
break;
} // end if
} // end for left
// handle if not found
if (!found) {
rightRecordTypeVisibility.default._text = 'false';
rightRecordTypeVisibility.visible._text = 'false';
leftRecordTypeVisibilities.push(rightRecordTypeVisibility);
} // end if
} // end for right
// update left profile record
mdapi_common_1.MdapiCommon.jsonToXmlFile(leftJsonObject, leftItem.filePath);
} // end if
I had the same problem. This code works fine:
return await gmail.users.messages.send({auth: auth, userId: 'me', resource: {raw: base64EncodedEmail}});
And this code gives an error:
const s = gmail.users.messages.send;
return await s({auth: auth, userId: 'me', resource: {raw: base64EncodedEmail}});
The error:
TypeError: Cannot read property 'context' of undefined
at send (/home/[redacted]/node_modules/googleapis/build/src/apis/gmail/v1.js:853:31)
at [the second line above]
I'm perplexed. There must be a difference between these two snippets, but I can't see how that could be the case.
:wave: the problem is that methods like gmail.users.messages.send are on classes which have an instance variable, in this case this.context.
One workaround would be to do something like this:
const s = gmail.users.messages.send.bind(gmail);
return await s({auth: auth, userId: 'me', resource: {raw: base64EncodedEmail}});
I would advise, in general, instead passing around gmail rather than a function off of the class however.
Hope this helps folks in this thread :smile:
Most helpful comment
I was getting this error and it turned out to be because i was passing around functions references like
androidpublisher.purchases.subscriptions.get. I was upgrading my package from a _much_ older version where this was working fine. To fix, I bound the functions likeandroidpublisher.purchases.subscriptions.get.bind(androidpublisher.purchases.subscriptions)