Syntax error with async function definition inside a class - node.js

I have a class with a few functions that I need to be async, but adding async in front of the function name gives me an error when compiling. (Testing with just one function atm)
class cataAPIService {
async getRouteDetails(route) {
var busID;
for(var i = 0; i < catabusRoutes.BUS_ROUTE_ID.buses.length; i++) {
if(catabusRoutes.BUS_ROUTE_ID.buses[i].name === route) {
busID = catabusRoutes.BUS_ROUTE_ID.buses[i].id;
console.log("Got bus id: " + busID);
}
}
var deferred = Promise.defer();
try {
const data = await axios.get("https://realtime.catabus.com/InfoPoint/rest/RouteDetails/Get/" + route);
console.log(data)
deferred.resolve(data)
} catch (error) {
console.log("Error in API call")
deferred.reject(error)
}
return deferred.promise
}
Removing async it complies fine but I lose the functionality that I need. Am I making a silly mistake and missing it? Thanks
Picture of console error:

Functions deploy to node 6 by default (you can see that in your console output). node 6 doesn't support async/await syntax. If you want to use async/await, you have to either deploy to node 8 (in beta), or use some sort of transpiled language like TypeScript.

This is correct syntax. Async functions are fully supported since Node 8. Syntax error will only occur if older Node version is used. Node should be updated to newer version if possible.
The code uses deferred antipattern and doesn't require async function. It could be:
async getRouteDetails(route) {
var busID;
for(var i = 0; i < catabusRoutes.BUS_ROUTE_ID.buses.length; i++) {
if(catabusRoutes.BUS_ROUTE_ID.buses[i].name === route) {
busID = catabusRoutes.BUS_ROUTE_ID.buses[i].id;
console.log("Got bus id: " + busID);
}
}
return axios.get("https://realtime.catabus.com/InfoPoint/rest/RouteDetails/Get/" + route)
.then(data => {
console.log(data);
return data;
})
.catch(error => {
console.log("Error in API call");
throw error;
});
}

Check your Node.js version.
Async functions are not supported by Node versions older than version 7.6.
You'll need to transpile your code (e.g. using Babel) to a version of JS that Node understands if you are using an older version.

Related

Cloud functions - update data on realtime database

Since the breaking changes in nodejs (moved to nodejs version 8), i having a serious errors and problems with my code. I have looked at google documents how to rewrite the functions but i still can't managed it.
On nodejs version 6 i wrote a function that triggers when a new item is added and then update other nodes in the realtime database
For example
// Keeps track of the length of the 'likes' child list in a separate property.
exports.countlikechange =
functions.database.ref('/likes/{postid}/{userUID}').onWrite(event => {
const collectionRef = event.data.ref.parent;
const model = event.data.val();
let genre = model.genre;
let videoID = model.videoID;
let userVideoID = model.userVideoID;
console.log("model: ",model);
console.log("genre: ",genre);
console.log("videoId: ",videoID);
console.log("userVideoID: ",userVideoID);
const countRef = collectionRef.child('likes');
// Return the promise from countRef.transaction() so our function
// waits for this async event to complete before it exits.
return countRef.transaction(current => {
if (event.data.exists() && !event.data.previous.exists()) {
const genreList = admin.database().ref(`${genre}/${videoID}/likes`).transaction(current => {
return (current || 0) + 1;
});
const userList = admin.database().ref(`users/${userVideoID}/likes`).transaction(current => {
return (current || 0) + 1;
});
const videoList = admin.database().ref(`videos/${userVideoID}/${videoID}/likes`).transaction(current => {
return (current || 0) + 1;
});
}
}).then(() => {
console.log('Counter updated.');
return null;
});
});
This func is no longer working because i have update nodejs to version 8.
On google documents the arguments changed, for example:
exports.makeUppercase = functions.database.ref('/messages/{pushId}/original')
.onWrite((change, context) => {
Also the return statment has change, it gives me error that i need to use promise.
So im kinda confused, how should i rewrite this func so when it triggers i'll update nodes in the realtime databse.
This doesn't actually have anything to do with the version of node. It has to do with the version of the firebase-functions SDK. You were using a very old pre-release version before. Since 1.0.0, the signatures have changed is a migration guide in documentation that describes the changes. In particular, read this section.
As of v 1.0 of the Firebase SDK for Cloud Functions, the event
parameter for asynchronous functions is obsolete. It has been replaced
by two new parameters: data and context.
You will need to learn the new APIs and port your code.
The requirements for return value have not changed. You are still obliged to return a promise the resolves when all the asynchronous work is complete in your function. If you are seeing a new error message about that, it's because you also upgraded your tools, and they are now checking unhandled promises for you.

Bluebird detection

For a library that supports any promise library, yet wants to know when Bluebird is specified, in which way should it verify for it? -
that would be simple and reliable
that would not likely break with later versions of Bluebird
var promise = require('any-promise-library');
function isBluebird(lib) {
// do the checks
}
console.log(isBluebird(promise));
_promise0 is internal value in BlueBird library and author of that library also uses that property to check if passed object is native promise or blueBird one.
var Blue = require("bluebird");
var promise = new Blue(function() {})
function isBluebird(obj) {
try {
return {}.hasOwnProperty.call(obj, "_promise0");
} catch (e) {
return false;
}
}
console.log(isBluebird(promise))
or, if you want to test library ...
var Blue = require("bluebird");
function isBluebird(promiseLibrary) {
var promise = new promiseLibrary(function() {})
try {
return {}.hasOwnProperty.call(promise, "_promise0");
} catch (e) {
return false;
}
}
console.log(isBluebird(Blue))
For future breaking changes - please be in contact with author - as internal method isAnyBluebirdPromise is internal - it can be changed with or without any reason
If you have access to Bluebird (that is if you can require it)
This is a check that "aPromise" is the same (version of) bluebird as the one available to you:
function isBluebird(aPromise) { // aPromise is the class of Promise, not an instance
var B;
try { var B = require ('bluebird') } catch(e) {}
if (!B) return false; // bluebird must be installed
return aPromise.getNewLibraryCopy === B.getNewLibraryCopy
}
Currently this also works if aPromise is the result of getNewLibraryCopy. But that is not guaranteed.
If you want the result of getNewLibraryCopy to be seen as different, compare aPromise.resolve === B.resolve
If you want to test a promise instance, you can compare aPromise.then === B.resolve().then. But that only works for the unmodified Bluebird. Intances of a getNewLibraryCopy promise will be different.

How to wait in node.js for a variable available on the cloud to have a specific value

I'm sorry if this is a basic question, but I am trying to implement a program in node.js that should wait for the value of a variable available trough a request to a cloud api (photon.variable()) to be 1. This variable should not be requested more than once per second. My first attempt is included in the sample code below. Despite knowing it does not work at all, I think it could be useful to show the functionality I would like to implement.
var photondata = 0;
while (photondata < 1)
{
setTimeout(function () {
photon.variable("witok", function(err, data) {
if (!err) {
console.log("data: ", data.result);
photondata = data.result;
}
else console.log(err);
})}, 1000);
}
Since you couldn't do async stuff in loops before, the traditional approach would be to create a function that adds itself to setTimeout for as long as needed, then calls some other function when it's done. You still need to do this in the browser if not using Babel.
These days, you can stop execution and wait for things to happen when using a generator function (which latest versions of Node now support). There are many libraries that will let you do this and I will advertise ours :)
CL.run(function* () {
var photondata = 0;
while (true) {
yield CL.try(function* () {
var data = yield photon.variable("witok", CL.cb());
console.log("data: ", data.result);
photondata = data.result;
}, function* (err) {
console.log(err.message);
});
if (photondata >= 1) break;
yield CL.sleep(1000);
}
// do whatever you need here
});

How can I satisfy promises aplus spec 2.2.4 in NodeJS?

I am writing an HTTP Promises package for nodeJS. I need it to be promises aplus compliant. I am using promises-aplus-tests - https://www.npmjs.com/package/promises-aplus-tests
I have created an adapter as follows:
var adapter = {
deferred: function() {
var d = {}
d.promise = new HTTPromise(new GETOptions('/path', DEFAULT_OPTIONS));
d.resolve = executorResponseFunc;
d.reject = executorRejectFunc;
return d;
}
}
promisesAplusTests(adapter, function (err) {
done(err);
});
My tests are failing on https://promisesaplus.com/#point-34 ...
with further help on https://promisesaplus.com/#point-67
2.2.4 onFulfilled or onRejected must not be called until the execution
context stack contains only platform code
3.1 Here “platform code” means engine, environment, and promise
implementation code. In practice, this requirement ensures that
onFulfilled and onRejected execute asynchronously, after the event
loop turn in which then is called, and with a fresh stack. This can be
implemented with either a “macro-task” mechanism such as setTimeout or
setImmediate, or with a “micro-task” mechanism such as
MutationObserver or process.nextTick. Since the promise implementation
is considered platform code, it may itself contain a task-scheduling
queue or “trampoline” in which the handlers are called.
But I can't get it passing this promises aplus test. I am using the bog standard JavaScript Promises library (which on its own passes the tests) documented at ...
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise
new Promise(executor);
new Promise(function(resolve, reject) { ... });
In the executor I have tried ...
if (response.statusCode === 200) {
process.nextTick(() => {
resolve(finalResponse);
});
} else {
process.nextTick(() => {
reject(finalResponse);
});
}
and also ...
process.nextTick(() => {
if (response.statusCode === 200) {
resolve(finalResponse);
} else {
reject(finalResponse);
}
});
There seems to be a lot of talk on the Internet but not many code examples of how to comply. Is there a code sample on how to satisfy this test and how you would use nextTick or another suitable solution?
It's worthing mentioning I have another call to reject within an HTTP error handler within the executor function.
I would like to apologise to Bergi, I think I have the answer to my stupidity but I would appreciate confirmation that my thinking is now correct ...
My initial confusion came from ...
https://www.npmjs.com/package/request-promise
I am writing a similar but more powerful npm tool.
They have the "then" badge, so obviously I wanted it!
I thought I needed to pass your tests (they have made some kind of attempt at it).
So I tried to pass your promises-aplus-tests
with my library, which uses promises heavily but is NOT a promise implementation.
I see ...
https://www.npmjs.com/package/promises-aplus-tests
says
This suite tests compliance of a promise implementation with the
Promises/A+ specification.
So I realise now that my package does NOT need to pass your tests and I am not as clever as I might have hoped :)
However, I am running a test to ensure that the Promise library we are using passes your tests during the build process. If it does not the build will fail.
My code is now ...
class HTTPromise {
constructor(options) {
... blah blah blah
let executor = THE_REAL_EXECUTOR;
return AppPromise(executor);
}
}
class HTTPromiseCompliance {
constructor(executor) {
return AppPromise(executor);
}
}
AppPromise looks like ...
module.exports = executor => {
return new Promise(executor);
}
and finally the test suite ...
describe('HTTPromises', function () {
it('should use a Promises/A+ compliant Promise library', function (done) {
this.timeout(0);
var adapter = {
deferred: function() {
var d = {}
var executor = function(resolve, reject) {
d.resolve = resolve
d.reject = reject
};
d.promise = new HTTPromiseCompliance(executor);
return d
}
}
promisesAplusTests(adapter, function (err) {
if (err != null) {
console.log('promises Aplus Tests failed with ' + err.failures + ' failures');
} else {
console.log('promises Aplus Tests passed');
}
done(err);
});
});
});
A grunt task for this is fired during the build process.
If anyone has any thoughts on 'my new thinking' I would be appreciative.
Thanks

Migrate Q to BlueBird (or Vow)

I'm current using the Q promise library in a Node/amqp app. I've read that the performance of Q vs libraries like BlueBird or Vow is... not so good.
Unfortunately, I can't figure out how to use BlueBird (or Vow) to replace my current Q usage patterns.
Here's an example:
this.Start = Q(ampq.connect(url, { heartbeat: heartbeat }))
.then((connection) => {
this.Connection = connection;
return Q(connection.createConfirmChannel());
})
.then((channel) => {
this.ConfirmChannel = channel;
channel.on('error', this.handleChannelError);
return true;
});
I should've mentioned - I'm using TypeScript... In this example I'm taking an amqplib promises, and creating a Q promise out of it (because I don't like the amqplib promises). How do I do that with BlueBird or Vow?
Another example is:
public myMethod(): Q.Promise<boolean> {
var ackDeferred = Q.defer<boolean>();
var handleChannelConfirm = (err, ok): void => {
if (err !== null) {
//message nacked!
ackDeferred.resolve(false);
}
else {
//message acked
ackDeferred.resolve(true);
}
}
...some other code here which invokes callback above...
return ackDeferred.promise;
}
How is that pattern implemented?
So my general questions is:
Are the performance differences I've read about true?
How do I migrate from Q to BlueBird or Vow, with a focus on those two patterns (but an explanation of using 'then' would be great, too)?
Yes, Bluebird is two orders of magnitude faster than Q, and is much more debuggable. You can look at the benchmarks yourself.
As for the code:
Q() maps to Promise.resolve in Bluebird (just like in ES6 native promises).*
Q.defer maps to Promise.defer() although it's a better option to use the promise constructor or automatic promisification as explained in this answer. In short, the promise constructor is throw safe.
Note* - once you've cast the promise, it'll assimilate thenables from other libraries automatically - so this is perfectly fine:
this.Start = Promise.resolve(ampq.connect(url, { heartbeat: heartbeat }))
.then((connection) => {
this.Connection = connection;
return connection.createConfirmChannel());
})
.then((channel) => {
this.ConfirmChannel = channel;
channel.on('error', this.handleChannelError);
return true;
});

Resources