Writing async/await version of a callback - node.js

I'm trying to rewrite a callback as async/await but following code doesn't work and results in high CPU at the commented line.
const kurento = require('kurento-client')
function getKurentoClient (kmsUrl) {
return new Promise((resolve, reject) => {
kurento(kmsUrl, (error, kurentoClient) => {
if (error) {
return reject(error)
} else {
return resolve(kurentoClient) // never returns
}
})
})
}
async function test () {
let result = await getKurentoClient('ws://localhost:8888/kurento')
console.log('done')
}
test()

From the mozilla.org website:
The Promise.resolve(value) method returns a Promise object that is resolved with the given value. If the value is a thenable (i.e. has a "then" method), the returned promise will "follow" that thenable, adopting its eventual state; if the value was a promise, that object becomes the result of the call to Promise.resolve; otherwise the returned promise will be fulfilled with the value.
And from bluebird GitHub:
when promises resolve other promises or things with then(aka thenables, like _kurentoClient in this case) - they have to wait for it to call then itself.
As you have guessed, kurento clients have a then function (so is a thenable) so the Promise is trying to resolve it. Because of a bug (or not a bug. Honestly, I have not researched enough to determine that) it keeps resolving itself forever.
As far as I see, seems that this kurento commit tries to fix it, resolving to an "untheanble". I see that the commit is from 31 Oct 2016 but the latest release is from Sep 2016 so I think that the fixed version is not deployed.

Related

Error: Transaction rejected with non-error: undefined

I am using knex npm version 0.15.2. while Rollback the transaction I'm getting the following error:
Error: Transaction rejected with non-error: undefined
Trx.rollback()
above function used for rollback.
Same code working for knex version 0.12.6
This is the function I used for commit/Rollback.
function Commit(pTrx, pIsCommit, pCallback) {
try {
var co = require("co");
var q = require('q');
var Q = q.defer();
co(function* () {
if (pIsCommit) {
yield pTrx.commit();
} else {
yield pTrx.rollback();
}
Q.resolve(pCallback('SUCCESS'));
}).catch(function (error) {
Q.reject(pCallback(error));
});
return Q.promise;
} catch (error) {
console.log(error)
}
}
This code could use some work. :) Here are a few things that pop out:
You don't need co or q anymore. Promises and async/await are built-in and much simpler to use. Async functions automatically return promises that will be resolved with the value returned or rejected if an error is thrown. Learn about async/await here: https://jsao.io/2017/07/how-to-get-use-and-close-a-db-connection-using-async-functions/
You shouldn't return success as a string. If the function completes without throwing an exception, then success is implied. I see people do this from time to time, but it's often for the wrong reasons.
You shouldn't accept callback in a function that returns a promise, it should be one or the other. The caller of your function will either pass a callback or await it's completion.
If you are going to use callbacks, then you should return null as the first parameter when successful. See the last sentence here: https://nodejs.org/en/knowledge/getting-started/control-flow/what-are-callbacks/
Your function name, Commit, starts with an uppercase. This convention is typically used to indicate that the function is a contstructor function and meant to be invoked with the new keyword.
Here's how the function could look once cleaned up:
async function commit(pTrx, pIsCommit) {
// Not using a try/catch. If an error is thrown the promise returned will be rejected.
if (pIsCommit) {
await pTrx.commit();
} else {
await pTrx.rollback();
}
// Not going to return anything. If we get to this point then success is implied when the promise is resolved.
}
A consumer of your function would call it with something like:
async function myWork() {
// do work; get pTrx
try {
await commit(pTrx, true);
// If I get here, then I can assume commit was successful, no need to check a return value of 'SUCCESS'
} catch (err) {
// handle error
}
}
It's hard to say where the issue is with the code in its current state. However, if the issue truly is with Knex, then you should probably post this as an issue in the Knex repo: https://github.com/tgriesser/knex/issues But you should write a reproducible test case that proves its an issue with Knex.

How to fix - Promise { <pending> } in Node.js and use it as variable anywhere

I'm accessing google API for converting coordinates into detailed objects using node-geocoder library from npmjs. Everything went well and I'm getting the expected object from geocoder API. The problem started the moment when I thought of using the data outside the promise function. I want to use the values outside the promise/async-await function.
Below is the code I've tried, Pls take a look and help me. TIA...
function goecoderPromiseFunction() {
return new Promise(function (resolve, reject) {
geocoder.reverse({ lat: 45.767, lon: 4.833 })
.then(data => {
cityName = data[0].city;
resolve(cityName);
})
.catch(err => {
console.log(err);
});
});
}
async function app() {
var a = await goecoderPromiseFunction();
return a;
}
var a = app();
console.log("a->", a);
I expect the variable "a" should print the city name "Lyon", but it prints
a-> Promise { < pending > }
The promise returned by the app function is never consumed, that is why it remains in a pending state.
Call then on the app function to get the result :
app().then(a => console.log("a->", a));
You can also use async/await :
(async function() {
var a = await app();
console.log("a->", a);
})();
An asynchronous function actually returns a promise that 'resolves' to the function's return value. You are therefore assigning a promise to the value of a. If you are in the global scope, you obviously cannot use async/await so you need to use either a self-executing async function or you need to run
a.then(data => console.log('a->', data));
to get what you are looking for.
Find out more about async functions here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function
It prints because console.log("a->", a); runs while promise haven't returned answer for a variable "a"
Note: you haven't used reject function, if there is an error you wont notice and may be that error was the required answer to be carried by variable "a" that's why it still pending i.e still waiting.
For more idea try to use reject function inside the catch block example reject(err)
instead of console it out as you've done

Node.js: Error when calling promise's callback function

I recently ran in a, for me, strange error. I have this simple function returning
a promise:
create(data) {
let _self = this;
return new Promise(function(resolve, reject) {
if(_self._validateData(data)) {
//is valid, so store in database...
} else {
reject(_self.error);
}
});
}
When the data is valid, the data is stored and there is no problem calling the resolve callback. However, when the data isn't valid, I immediately call the reject function. But when I do so I receive an error.
Is it possible that, at the time the process reaches the call of reject, the reject was not set by the calling function? Because when I run following code, it works perfectly:
create(data) {
let _self = this;
return new Promise(function(resolve, reject) {
if(_self._validateData(data)) {
//is valid, so store in database...
} else {
setTimeout(function(){reject(_self.error);}, 100);
}
});
}
I really want to avoid using this solution. Not only because it looks ugly to me, but also because I am not even sure, if I understand the error.
So any ideas what is wrong here and how can I solve this?
For everybody facing the same problem:
It is not really an error but a "feature" of VS Code Debugger (using v8).
See here and here for further information. The issue is called "synchron rejection". Also, I only misinterpreted it as an error. It is not. The debugger just pauses and points out, that there is an synchron rejection
I moved on using bluebird promises
Is it possible that, at the time the process reaches the call of reject, the reject was not set by the calling function?
No, that's not possible. You can reject the promise at any time.
Because when I [put it in a timeout], it works perfectly
I'll guess that you did not set up a rejection handler (.catch(…)) on your promise chain soon enough, and are receiving a "possibly unhandled promise rejection" warning because of that.

Using Promise with CouchDB nano & forEach

I need help with debugging this code/or learn efficient way to do it- I tried using bluebird.each to capture all executions within my forEach, but didn't get it work. Same with setting up a new promise with pure javascript. I need help how to execute my forEach FIRST and move on.
let arr = [];
let fields = ['environment', 'habitat', 'earth]
Promise.each(fields, field => {
nano.db.use(field).view('options', 'options')
.spread((body, header) => {
arr.push(body.rows);
})
}).then(() => console.log(arr))
Expected outcome:
arr to console.log ====> [1,2,3,4,5]
Actual outcome:
arr is an empty array ====> [ ]
I see it's a problem with asynchronicity, but I can't seem to figure out how to actually make this work. any input or resources will be greatly appreciated!
I haven't actually ran your code so sorry if I'm incorrect, but from looking at it and the bluebird docs I assume the correction you need to make is return your nano.db call wrapped in a promise inside the Promise.each
let arr = [];
let fields = ['environment', 'habitat', 'earth']
Promise.each(fields, field => {
return new Promise ((resolve, reject) => {
nano.db.use(field).view('options', 'options')
.spread((body, header) => {
arr.push(body.rows);
resolve();
})
});
}).then(() => console.log(arr))
I believe your assumption is right that you're having a problem with asynchronicity when getting an empty array back instead of what you expect. I'm assuming the .then method is firing before the nano.db gets back with the data.
I wrapped your call of nano.db in a promise so that it will await nano.db finishing since Promise.each supports returning promises inside it.
Bluebird's promise docs state with Promise.each.
If the iterator function returns a promise or a thenable, then the
result of the promise is awaited before continuing with next
iteration.
So, if a promise is not returned in your Promise.each and anything that is asynchronous happens inside then just as with a then or a catch method on a promise under the same circumstances.
As I do not know bluebird there may be a way to change that promise to be more bluebird like. The promise I wrapped around the nano.db call is just a normal es6 promise which bluebird may or may not have a different api for creating promises.

Intern: Testing async unit tests with ES6 promises

I have some async functions that I need to test via Intern. Each uses ES6 promises.
In the Intern docs, it says that test functions that return a promise pass as soon as that promise is resolved. However, I not only care about whether the async function I am testing is resolved/rejected, I also want to check to make sure the resolved value is correct.
Example: I have my function:
function getSomething() {
return new Promise((resolve, reject) => {
// do some async stuff and resolve when done
setTimeout(function() {
resolve('the value');
}, 1000);
});
}
Then I have the test method:
tdd.test('getSomething', function() {
return new Promise((resolve, reject) => {
getSomething().then(function(value) {
// I want to resolve/reject the promise BASED ON the assertion -- if the assertion fails, I want to reject the promise; if it succeeds, I want to resolve it
assert.equal(value, 'the value', 'getSomething should return "the value".');
resolve();
});
});
}
I've noticed this doesn't work -- if the assertion fails in my test, the resolve() never gets called.
How would I be able to resolve/reject the promise conditioned upon the assertion? Should I wrap the assertion in a try/catch? I didn't see any documentation on the Intern docs about this (and most were using this.async() instead of ES6 promises).
What's happening in your code is that the assertion in the getSomething callback is throwing an exception, and that's preventing resolve from being called. The getSomething promise will be rejected, but since you're not returning it in the wrapper promise's initializer, the wrapper promise is never resolved or rejected.
There is no need to wrap the promise returned by getSomething in a new promise. Just return it directly.

Resources