I have a feeling that I'm just trying to fit a square peg into a round hole, but I'm trying to apply some things with Angular2 and Typescript, and I'm banging my head against a wall.
I've written a Javascript module that acts as an API client library to an API I'm consuming. It just packages some convenience things like setting up the correct API keys, switching keys based on certain desired data, etc. It's basically just a convenience library.
Most of the methods follow a pattern where you provide a query term and then execute a callback.
So for example:
API.searchAutocomplete("angular", function(err, data) {
// handle the data/error
});
Inside that method:
searchAutocomplete: function(query, callback) {
// set up request with data payload, url, headers, etc
$.ajax(settings)
.done(function(response) {
// callback with success
})
.fail(function () {
// callback with error
});
}
I'm struggling with trying to understand how to run this function in Typescript in an Angular service with a Promise (square peg round hole). Or should I just pass a callback within the service and treat it like it's Javascript?
My attempt:
public getAutocomplete(query:string): Promise < any > {
return new Promise((resolve, reject) => {
API.searchAutocomplete(query, function (err, result) {
if (err) {
reject(err);
return;
}
resolve(result);
});
});
}
Second, I've been able to load the library into my Angular app but I can't seem to actually make any of the requests. Even if I break in the console and access the library object it doesn't seem to actually make any network requests. Which I really don't understand.
Edit: I've sorted this part out.
When I made my service call return a promise, I had to subscribe to the promise otherwise I wouldn't execute it correctly. I think I still need to understand how to write my service call to return an observable and map the callback response.
As expected, I was trying to do more work than I should have.
This is pretty simple, just return an observable that calls the external library.
public autoCompleteResults(query: string): Observable<string[]> {
return new Observable<string[]>(observer => {
API.searchAutocomplete(query, function (err, result) {
if (err) {
console.log(err);
observer.next([]);
// OR
observer.error(err);
return;
}
observer.next(result);
});
});
}
Related
Up until now for me the concept of a Node Worker has been one of those things that sounds interesting and I will find out about one day.
Well that day has come and I am asking for some help.
I need to call a web service and then process the data returned. I can call the service with an XMLHttpRequest, but then I have to get useful data out of it.
There is a nice node module that both calls the service and returns the data in a useful form with one call.
I can set up Node worker (in Wakanda) to do this and verify that it works.
My problem is handling the asynchronous call in the proxy.
The call to the node module looks like this:
myModule.getData(param, (err, data) => {
// data is an object containing everything I want.
// if I get data I want to return it to the proxy
// if I get an err I want to return the error to the proxy
});
So my wrapper code looks something like this:
function doSomething(param){
// call proxy with param
// wait for result
// return result
}
This all sounds like something I should know how to do. However I think I am struggling with too many new things and getting myself absolutely confused.
PS: I did try Threadify but couldn't work out how to get the worker to return the error it received.
I would really appreciate any help or pointers here.
If I am correctly understanding your issue, you cannot return a value from a function AFTER an asynchronous call completes. You need to handle the data within the myModule.getData callback.
If you would rather handle it in a calling function (like doSomething), you can use a promise to "return" a value.
function myProxy(param) {
return new Promise((resolve, reject) => {
myModule.getData(param, (err, data) => {
if (!err) { // or however you determine an error occurred.
resolve(data); // if I get data I want to return it to the proxy
} else {
reject(err); // if I get an err I want to return the error to the proxy
}
});
});
}
function doSomething(param){
myProxy(param).then(data => {
// Handle the data here.
}).catch(err => {
// Handle the error here.
});
}
I am trying to understand how promisifyAll works. i am trying hard to understand the example given in their documentation. Can anyone please give me a simple example, how it works? I am trying to understand the concept and how we can use it. Thank you
var objects = {};
objects.first = function(){
console.log("First one is executed");
}
objects.second = function(){
console.log("second one is executed");
}
objects.third = function(){
console.log("third one is executed");
}
how can we promisify the objects variable? or something like that.
First, you need to understand how a nodeFunction works. It takes a callback function as the last argument. This callback takes two arguments, the first one is error and the second the data. Consider for example require("fs").readFile:
// This is the callback
function callback (error, data) {
if (error) {
console.error('There was an error', error)
} else {
console.log('This is the data', data)
}
}
require('fs').readFile('my-file.txt', callback)
Note that this is a convention, there's nothing in JS itself that enforces it.
Let's move to Promise.promisify now. This method takes a nodeFunction and returns a promisified version of it. This is more or less what it does:
function promisifiedReadFile (filePath) {
return new Promise(function (fulfill, reject) {
require('fs').readFile(path, function (error, data) {
if (error) { reject(error) } else { fulfill(data) }
})
})
}
It's a bit verbose but as you can see you now have a version of readFile that returns a promise instead of accepting a callback. Of course, this example is hard-coded for readFile, Promise.promisify works for any nodeFunction instead:
const promisifiedReadFile = Promise.promisify(require('fs').readFile)
The two promisifiedReadFile methods work in the same way.
Last, Promise.promisifyAll takes an object, goes through it and finds all the methods, it then applies Promise.promisify to each of them.
So, if you call Promise.promisifyAll(require('fs')) you get back a version of the fs module where all the methods return promises instead of accepting callbacks.
About your example I'm not sure what you're trying to achieve but the methods you defined are not nodeFunctions so they can't be promisified.
I am implementing an API to manage a MySQL database from Nodejs, and I want to keep my code clean as the work I intend to do can take me to have a lot of nested connection.query functions all over the place, so I've decided to separate as many as the queries I could into separate functions.
To start I wanted to do a function to check if there is an existing element already on the table, like this:
function validator(item) {
return new Promise(function(err,done) {
connection.query('select * from items where item_id = ?', [item.id] , function(err,rows){
console.log(rows);
console.log("above row object");
if (err) {
return done(false);
}
if (rows.length) {
console.log('That item is already in the DB.');
return done(false);
} else {
console.log('That item is new.');
return done(true);
}
});
});
}
And then I want to use it like this:
var insert = function (item, done) {
validator(item).then(function(err,done) {
console.log('here I go: '+done);
if(done) {
console.log('good');
} else{
console.log('bad')
}
);
}
But it does not work like I expected, the first function accurately detects if an item exists or not, but the second one never never reaches the "here I go" print.
I have checked Use promise to process MySQL return value in node.js, Javascript Promise node.js? and Javascript & promises with Q - closure problems in promises but the conclussion I reach is that this is a classic PEBCAK problem, such as that I'm a very incompetent javascript programmer and can't wrap my head around the callbacks and promises all that well so I'm managing them the wrong way.
The first callback you pass to the Promise constructor isn't the failing one.
Change
return new Promise(function(err,done) {
into
return new Promise(function(done, reject) {
and call it like this:
validator(item).then(function(done) {
(by the way it's very confusing to call done both the resolve callback and the result).
Handle the incoming error: Change
if (err) {
return done(false);
}
into
if (err) {
reject(err);
}
and don't forget to catch those errors.
Also, it's probably outside the scope of this QA but you usually take and release connections. You should probably have a look at promises ready mysql drivers.
I have multiple Meteor.calls, where each methods depends on the response of another Meteor method.
Client
Meteor.call('methodOne', function(err, resOne){
if(!err){
Meteor.call('methodTwo', resOne, function(err, resTwo){
if(!err){
Meteor.call('methodThree', resTwo, function(err, resThree){
if(err){
console.log(err);
}
})
}
});
}
});
From Meteor's documentation I know
"Methods called on the client run asynchronously, so you need to pass a callback in order to observe the result of the call."
I know I can create yet another Meteor Method on the server to execute methods 'methodOne', 'MethodTwo', 'MethodThree' wrapped using Meteor.async, or sequentially without the callback all together. But I am worried this path will cause my meteor methods to get bloated and entangled, leading to spaghetti code. I would rather keep each Meteor method simple with one job to do and find a more elegant way of chaining the calls on the client. Any ideas, is there any way to use Promises on the client?
Since the other answer suggests RSVP this answer will suggest Bluebird which is actually the fastest promise library when running real benchmarks. Rather than a micro benchmark that does not really measure anything meaningful. Anyway, I'm not picking it for performance, I'm picking it here because it's also the easiest to use and the one with the best debuggability.
Unlike the other answer, this one also does not suppress errors and the cost of making the function return a promise is marginal since no promise constructor is called.
var call = Promise.promisify(Meteor.call, Meteor);
var calls = call("methodOne").
then(call.bind(Meteor, "methodTwo")).
then(call.bind(Meteor, "methodThree"));
calls.then(function(resThree){
console.log("Got Response!", resThree);
}).catch(function(err){
console.log("Got Error", err);
});
Your approach on the client results in a lot more round trips between the server and the browser. I know you indicated that you were worried about spaghetti code on the server and I don't have visibility into your application as you do, but just going by the example you provide, it seems like an ideal place to wrap all three calls on the server and make only one call from the client, IMHO.
EDIT: You're probably better off looking at #Benjamin Gruenbaum answer, which not only results in better performance, but also provides much more concise code.
Promises - yes there is.
I like RSVP very much, why? Simply because it's the fastest one. (quick benchmark: jsperf ).
Here's quick re-write of your code:
var promise = new RSVP.Promise(function(fulfill, reject) {
Meteor.call('methodOne', '', function(err, resOne) {
if (!err) {
return reject(err);
}
fulfill(resOne);
});
});
promise.then(function(resOne) {
return new RSVP.Promise(function(fulfill, reject) {
Meteor.call('methodTwo', resOne, function(err, resTwo) {
if (err) {
return reject(err);
}
fulfill(resTwo);
});
});
}).then(function(resTwo) {
return new RSVP.Promise(function(fulfill, reject) {
Meteor.call('methodTwo', resTwo, function(err, resThree) {
if (err) {
reject(err);
}
fulfill(resThree);
});
});
}).then(function(resThree) {
// resThree is available - continue as you like
console.log(resThree);
}).catch(function(err) {
console.log(err);
});
That's the way to prevent "the ever rightward drift" of your code.
Promises are cool, use them.
Probably asked before, but after the serious searching I'm still not able to find a proper solution. Please consider something like this:
function compute() {
asyncCall(args, function(err, result) {
});
/* 'join thread here' */
}
Even though asyncCall is asynchronous I'd like to use the result and return it from the function compute synchronously. asyncCall is a library call and I can't modify it in any way.
How to wait properly for the asynchronous result without setTimeout and watching a conditional variable? This is possible but suboptimal.
not sure how you can really use something that doesn't exist yet, but it's easy enough to return a slot where the result will be:
function compute() {
var rez=[];
asyncCall(args, function(err, result) {
rez[0]=result;
if(rez.onchange){ rez.onchange(result); }
});
/* 'join thread here' */
return rez;
}
now, you can refer to the [0] property of the return, and once the callback comes in, compute()[0] will have the result. It will also fire an event handler you can attach to the returned array that will fire when the data updates inside the callback.
i would use something more formal like a promise or secondary callback, but that's me...
EDIT: how to integrate a callback upstream:
// sync (old and busted):
function render(){
var myView=compute();
mainDiv.innerHTML=myView;
}
//async using my re-modified compute():
function render(){
var that=compute();
that.onchange=function(e){ mainDiv.innerHTML=e; }
}
see how making it wait only added a single wrapper in the render function?
There's no await syntax in browsers that is widely available. Your options are generally limited to Callback patterns or Promises.
NodeJS follows a callback pattern for most async methods.
function someAsyncMethod(options, callback) {
//callback = function(error, data)
// when there is an error, it is the first parameter, otherwise use null
doSomethingAsync(function(){
callback(null, response);
});
}
....
someAsyncMethod({...}, function(err, data) {
if (err) return alert("OMG! FAilZ!");
// use data
});
Another common implementation is promises, such as jQuery's .ajax() method...
var px = $.ajax({...});
px.data(function(data, xhr, status){
//runs when data returns.
});
px.fail(function(err,xhr, status){
//runs when an error occurs
});
Promises are similar to events...
Of the two methods above, the callback syntax tends to be easier to implement and follow, but can lead to deeply nested callback trees, though you can use utility patterns, methods like async to overcome this.