If I yield promises in Koa, they may be rejected:
function fetch = (){
var deferred = q.defer();
//Some async action which calls deferred.reject();
return deferred.promise;
}
this.body = yield fetch(); //bad, not going to work
Is there a error-handling pattern in Koa to handle this besides explicitly unwrapping the promise with then and handling the error explicitly?
Try/Catch. Under the hood koajs uses co. Check out the docs for co, which describes error handling a little better.
function fetch = (){
var deferred = q.defer();
//Some async action which calls deferred.reject();
return deferred.promise;
}
try{
this.body = yield fetch(); //bad, not going to work
}
catch(err){
this.throw('something exploded');
}
Here is an rudimentary example of what's happening with the promise:
function * someGenerator () {
let result;
try{
result = yield fetch();
console.log('won\'t make it here...');
}
catch(err){
console.log(err);
}
console.log('will make it here...');
}
// Normally co() does everything below this line, I'm including it for
// better understanding
// instantiate the generator
let gen = someGenerator();
// calling gen.next() starts execution of code up until the first yield
// or the function returns.
let result = gen.next();
// the value returned by next() is an object with 2 attributes
// value is what is returned by the yielded item, a promise in your example
// and done which is a boolean that indicates if the generator was run
// to completion
// ie result = {value: promise, done: false}
// now we can just call the then function on the returned promise
result.value.then(function(result){
// calling .next(result) restarts the generator, returning the result
// to the left of the yield keyword
gen.next(result);
}, function(err){
// however if there happened to be an error, calling gen.throw(err)
// restarts the generator and throws an error that can be caught by
// a try / catch block.
// This isn't really the intention of generators, just a clever hack
// that allows you to code in a synchronous style (yet still async code)
gen.throw(err);
});
If your still uncertain, here are a couple other things that might help:
Watch my screencast on JavaScript Generators here: http://knowthen.com/episode-2-understanding-javascript-generators/
and/or try the following code:
// test.js
'use strict';
let co = require('co'),
Promise = require('bluebird');
function fetch () {
let deffered = Promise.defer();
deffered.reject(new Error('Some Error'));
return deffered.promise;
}
co.wrap(function *(){
let result;
try{
result = yield fetch();
console.log('won\'t make it here...');
}
catch(err){
console.log(err);
}
console.log('will make it here...');
})();
then on the console run
$ node test.js
[Error: Some Error]
will make it here...
You can easily drop in the package koa-better-error-handler with npm install --save koa-better-error-handler and then implement it as such:
const errorHandler = require('koa-better-error-handler');
// override koa's undocumented error handler
app.context.onerror = errorHandler;
More info: https://github.com/niftylettuce/koa-better-error-handler
Related
How to use the asynchronous Await in Node.js by using these function and how
The request.get() function returns a Promise by which user will await...
I have tried the Below code so far and also gave the explanation below
async function fun1(req, res){
let response = await request.get('http://localhost:3000');
if (response.err) { console.log('error');}
else { console.log('fetched response');
}
The code above basically asks the javascript engine running the code to wait for the request.get() function to complete before moving on to the next line to execute it. The request.get() function returns a Promise for which user will await . Before async/await, if it needs to be made sure that the functions are running in the desired sequence, that is one after the another, chain them one after the another or register callbacks.
async function fun1(req, res){
let response = await request.get('http://localhost:3000');
if (response.err) { console.log('error');}
else { console.log('fetched response');
}
request package does not use return promise. Use the request-promise package which wraps the request with Promise.
You can use it like:
const rp = require('request-promise')
async function getSomeData() {
try {
const url = 'http://some.com'
// waits for promise to resolve
const data = await rp(url)
// data contains resolved value if successfull
// continue some other stuff
...
} catch (e) {
// handle error if error occurred
console.error(e)
}
}
I'm in the process of building a small Library that relies heavily on asynchronicity and I'm trying to support NodeJs callback style, Promises and async/await with minimal duplication of functional code.
So, as example take the following ( it doesn't matters what it does)
class Someclass{
constructor(){}
asyncMethod(someData, cb){
var commonVar = ''
if (cb) { // ******* Callback Requested
doSomething()
var result=usingCallbacks()
if (!result) cb('Error')
cb(null, result)
} else{ // ******** we should use a promise
return new Promise((resolve,reject) => {
doSomething()
var result=usingPromises()
if (!result) reject(err)
resolve(result)
})
}
}
}
So i'm stuck on how to build the async/awit part here. Any ideas?
Nothing else is required since await can await anything that returns a Promise (or something promise-like).
In other words, this should "just work":
async useLibFn() {
await someclass.asyncMethod('foo');
}
Under the covers, async/await are just syntactic sugar for promises.
async causes a function to always return a promise. Basically equivalent to:
function someFn() {
return new Promise(function(resolve, reject) {
try {
// actual fn body
} catch (ex) {
reject(ex);
}
});
}
await takes some expression and resolves it asynchronously. If the value is promisey, it waits for the promise to resolve (calls then()). Otherwise, it resolves with the value on the next tick. Basically equivalent to:
Promise.resolve(rval).then(...)
Hello i have been using a library called deasync it allows me to get things done in a cleaner way, i have a method like this,
syncGetMany: function(model, query){
var ret;
setTimeout(function(){
model.find(query, (error, body) => {
if(body){
//Awesome got the data
ret= body
}
else{
//What a cruel world
// No data, fall back to an empty array
ret = [];
}
});
},0);
while(ret === undefined) {
require('deasync').sleep(0);
}
//returns an empty array or the real data
return ret;
},
Then i simply call it like this.
var data = syncGetMany(MongooseModel, queryObj);
// the rest of my code
QUESTION: is there a way to get this done using ES6, or any similar library.
PS: Not duplicate as other questions are not relevant to my context
simplest way to get this code more cleaner is to use async/await, it's available in node.js version => 7.0. If I think well your model.find method returns promise.
async syncGetMany (model, query) {
let ret;
ret = await model.find(query);
//ret is keeping body from response now, if error occured error is throwed as promise exception
//Could do some sync ops on ret variable
return ret;
}
When you are using async/await you should put your method execution into try/catch. But you can also catch errors inside syncGetMany method, probably it should looks like this:
async syncGetMany(model, query) {
let ret;
try {
ret = await model.find(query);
return ret;
} catch(err) {
console.error(err);
return []; //empty array or any error string/object
}
}
And your execution looks like you wrote with additional await operator (using es6 provide let/const operators for var operator replacement)
let data = await syncGetMany(MongooseModel, queryObj);
Article with async/await explanation:
https://blog.risingstack.com/async-await-node-js-7-nightly/
If you don't want to use Node v7.0 you should code something like this using promises and generators.
https://medium.com/#rdsubhas/es6-from-callbacks-to-promises-to-generators-87f1c0cd8f2e
I hope I helped.
Update
So when your mongoose instance doesn't supports promises there are three options (depends I think on node versions). In my opinion promises are cleaner way to make asynchronous request so I suggest using them.
First option (native promises):
syncGetMany(model, query) {
return new Promise((resolve, reject) => {
model.find(query, (err, res) => {
if(err) {
return reject(err);
}
resolve(res);
});
});
}
Second option (bluebird library, added Async postfix to all methods):
const mongoose = require( 'mongoose' );
const Promise = require('bluebird');
Promise.promisifyAll( mongoose );
async syncGetMany(model, query) {
let ret;
try {
ret = await model.findAsync(query);
return ret;
} catch(err) {
console.error(err);
return []; //empty array or any error string/object
}
}
Third option (Node version => 8.0):
Using native promisify on function:
https://nodejs.org/dist/latest-v8.x/docs/api/util.html#util_util_promisify_original
On our synchronous part (with async operator before function construction):
let data = await syncGetMany(MongooseModel, queryObj);
You can write and execute logic as if it was synchronous using nsynjs:
function synhronousCode(model, query) {
function syncGetMany(model, query){
return model.find(query).data; // data will contain result of resolved promise at this point
};
var data = syncGetMany(model, query);
// do stuff with data
}
var nsynjs = require('nsynjs');
....
nsynjs.run(synhronousCode,{},model, query, function(){
console.log('synhronousCode done');
});
nsynjs will evaluate code in synhronousCode in sequential manner: if some function returns promise (as model.find does), nsynjs will pause execution and wait until promise is resolved, assigns result to data property of returned value, and then continue execution.
So I'm new to Node.js and Im just wondering if the way I have my code setup makes sense. Im coming from a Java background so the nested callback structure is new. I have a Node program that runs a bunch of code that I broke down into different methods. The thing is that the methods need to be called in order. My code has this structure right now:
functionOne(data, callback(err) {
functionTwo(data, callback(err) {
functionThree(data, callback(err) {
functionFour(data, callback(err) {
//Code
});
});
});
});
This is very minimalistic, but is this structure ok? With Java, I'd take the return values of all the methods, then just pass them to the next function. From my understanding so far, the Java approach I just mentioned is one of the main things that Node.js was trying to eliminate. But anyway... Does that structure look ok, and is that how its intended to look? Just want to be sure that I'm not making any major errors with Node in general. Thanks!
Your code structure looks fine if you work with callback pattern.
But if you're interested in make your code cleaner and readable you would like to use Promises in your asynchronous function, so instead of pass a callback to your functions you could do something like this :
function asyncFunction (data){
return new Promise(function(resolve, reject){
// Do something with data
// Here you can call reject(error) to throw an error
resolve();
});
}
And instead of nested function callbacks you can call then method of Promise.
asyncFunction(data)
.then(function(){
// Promise resolved
// Something has been done with data
});
With Promises you can also execute async fuctions in parallel :
Promise.all([asyncFunctionA(data), asyncFunctionB(data), asyncFunctionC(data)])
.then(function(){...});
EDIT
If you need to pass values of one function to another, your code should look like this :
asyncFunctionA(data)
.then(function(dataA){
return asyncFunctionB(dataA);
})
.then(function(dataB){
return asyncFunctionC(dataB);
})
.then(function(dataC){
// ...
});
You should try to use promises to avoid your callback hell, so it could be something like these...
const Q = require('q'); // you can do a research for this module.
var myModule = {};
myModule.functionOne = (params) => {
const deferred = Q.defer(); // wait for this to complete
// body function
deferred.resolve(data); // this would be the result of this function
return deferred.promise; // data is the output on your function
}
myModule.functionTwo = (params) => {
const deferred = Q.defer(); // wait for this to complete
// body function
deferred.resolve(data); // this would be the result of this function
return deferred.promise; // data is the output on your function
}
myModule.doAll = (params) => {
myModule.functionOne(params)
.then((outputFunctionOne) => {
// this is called after functionOne ends
return myModule.functionTwo(outputFunctionOne);
})
.then((outputFunctionTwo) => {
// this is called after function 2 ends
if (outputFunctionTwo.success) {
// if everything ok, resolve the promise with the final output
deferred.resolve(outputFunctionTwo);
} else {
// reject the promise with an error message
deferred.reject('error');
}
})
.fail((err) => {
// this is call if the promise is rejected or an exception is thrown
console.log(err); // TODO: Error handling
})
.done();
}
module.exports = myModule;
You can Chain as many promises as you want really easily, that way you get rid of the callback hell. Best part, you can do promises on Javascript or Node.js
Reference Link https://github.com/kriskowal/q
Hope this helps
Most of the other answers give Promise/A as the answer to your callback woes. This is correct, and will work for you. However I'd like to give you another option, if you are willing to drop javascript as your working language.
Introducing Iced Coffee, a branch of the CoffeeScript project.
With Iced Coffee you would write:
await functionOne data, defer err
await functionTwo data, defer err2
await functionThree data, defer err3
//etc
This then compiles to the CoffeeScript:
functionOne data, (err) ->
functionTwo data, (err2) ->
functionThree data, (err3) ->
//etc
Which then compiles to your Javascript.
functionOne(data, callback(err) {
functionTwo(data, callback(err2) {
functionThree(data, callback(err3) {
//etc
});
});
});
I'm trying to promisify a 3rd party library that doesn't use the callback(err, data) pattern. Instead they always return callback(data) and throw on errors.
Promise.promisifyAll(horse);
var p = Promise.defer();
horse.drinkAsync()
.error(function(data)
{
p.fulfill(data);
})
.catch(function (err)
{
console.error('error occured', err);
});
return p.promise;
What is a nice way to wrap such a behavior with promises and still have it look ok and allow to catch the thrown error? The catch clause doesn't trigger and the application crashes.
From Bluebird 2.1 on, you can now customize promisifyAll with a custom promisification handler:
function noErrPromisifier(originalMethod){
return function promisified() {
var args = [].slice.call(arguments); // might want to use smarter
var self = this // promisification if performance critical
return new Promise(function(resolve,reject){
args.push(resolve);
originalMethod.apply(self,args); // call with arguments
});
};
}
var horse = Promise.promisifyAll(require("horse"), {
promisifier: noErrPromisifier
});
horse.drinkAsync().then(function(data){
// Can use here, ow promisified normally.
});
If the original method throws asynchronously, there is really no way around wrapping it in a domain, although I've never seen a library that acts that poorly.