the function is in function's parameter,for example
function getAcceptLanguages() {
chrome.i18n.getAcceptLanguages(function(languageList) {
var languages = languageList.join(",");
setChildTextNode('languageSpan',
chrome.i18n.getMessage("chrome_accept_languages", languages));
})
}
the function is " chrome.i18n.getAcceptLanguages()"
the function in function's parameter is :function(languageList) {...}
i really dont get it....how to send data to the languageList.
hope someone can answer for me
chrome.i18n.getAcceptLanguages is a async operation, so it need a callback function to return the languageList result. The browser will find the accept languages, then call the callback function with the result languageList as the parameter. So that you can get the result in the callback function.
Related
I'm using instagram-scraping module to display all posts with a specific hash tag but I get an issue using a function to return finded items.
// in my middleware
function getInstagramPostsByHashTag(hashtag) {
return ig.scrapeTag(hashtag).then(result => {
console.log(result); // all posts are displayed in my console
return result;
});
}
// in my ejs template i send the function getInstagramPostsByHashTag()
<%=getInstagramPostsByHashTag("instagram")%> // nothing is displayed
You can't return the posts from the function because the function has already returned at this point. That's because .then() is asynchronous. It executes the provided callback when the work (fetching the posts) is done, but the function continues to run after the call to .then(), and because you return nothing, you get nothing.
If you want a function to return the result of an asynchronous operation, you have to return a promise from the function itself. To help developers with that, there's the async function that automatically returns a promise. In an async function, you can wait for other promises with the await keyword. Your function would look like this as an async function:
async function getInstagramPostsByHashTag(hashtag) {
return await ig.scrapeTag(hashtag)
}
But this is redundant because it returns exactly the same as a direct call to ig.scrapeTag(hashtag) would do. I don't really know ejs but I think the best thing you could do is something like this (only pseudocode, again, I don't know how rendering with ejs works):
posts = insta.scrapeTag("blablabla")
then
ejs.render("<%=posts%>", {posts})
I am reviewing a sample nodejs server code, which is working fine. but could not understand the following code:
var handlers = {};
// Creating a sample handler
handlers.sample = function(data,callback){
callback(406,{'name':'sample handler'}); // How is this line of code working??
};
// Creating a not found handler
handlers.notFound = function(data,callback){
callback(404); // How is this line of code working??
};
In the entire code there is no implementation of "callback" function then how
callback(406,{'name':'sample handler'});
and
callback(404);
are working?
Please suggest. Thanks.
callback isn't implemented in the code you posted; it's a named parameter.
To call one of the functions that requires a callback, you'll need to pass it in as an argument, like:
handlers.sample("some data", () => console.log("I'm in a callback!));
The first argument ("some data") goes in the data parameter, and the second argument (() => console.log("I'm in a callback!)) goes in the callback parameter. When callback(404) is run, it executes the callback function (in the above example, it would do console.log("I'm in a callback!)).
Basically, when you call handlers.sample, you should pass a function as your second argument, and that function will be called, usually asynchronously, and presumably after something is done with the data you pass as the first argument. For example, based on the code you provided:
handlers.sample(dataObject, (number, object) => {
console.log(number)
console.log(object.name)
})
would yield this result in the console:
406
sample handler
I’m curious if this is a public library you are seeing this code in, so we can take a closer look?
I did a further digging in into this and found that
selectedHandler
in the following code (this is not mentioned in the question) is getting resolved into handlers.sample or handlers.notFound variable names based on some logic (which is not mentioned here)
selectedHandler(data,function(status,payloadData){
// somelogic with the status and payloadData
});
And second parameter of this function which is a complete function in itself
function(status,payloadData){
// somelogic with the status and payloadData
}
is going as the second parameter in handlers.sample or handlers.notFound which is a Callback. So execution of Callback in the current context is execution of this function (this function is anonymous because it has no name and getting executed as Callback)
I am very confused when it comes to javascript callbacks... Especially when attempting to learn node at the same time.
You see, I understand the concept of passing a function as a parameter to another function but what confuses me mostly are the premade modules that "accept" callbacks functions.
For example a simple request looks like so:
var request = require('request');
var url = 'http://www.google.com';
request.get(url, function(error, response, body) {
if(error){
console.log('This request resulted in an error', error);
}
console.log(body);
});
This get method accepts a url and a callback.
Who defines that a callback is accepted? The developer of the specific method?
Also, the 3 parameters that we pass within the function (error, response, and body)... how does the request module know to populate these variables with data on return?
Imagine get implemented more or less like
function get(url, callback) {
var response = they somehow retrieve the response;
var body = they somehow parse the body;
var error = ...;
// they call you back using your callback
callback( error, response, body );
}
How these values are computed is irrelevant (this is their actual job) but then they just call you back assuming your function actually accepts three arguments in given order (if not you just get a runtime error).
In this sense they also kind of "accept" your callback by ... well, calling it back :) There is no worry about the number of arguments as Javascript is very "forgiving" - methods can be called with any number of arguments, including less or more arguments than the function expects.
Take this as an example:
// they provide 3 arguments
function get( callback ) {
callback( 0, 1, 2 );
}
// but you seem to expect none
get( function() {
});
The get assumes that the callback accepts three arguments while I pass a method that supposedly doesn't accept less arguments. This works, although the three arguments, 0, 1 and 2 are not bound to any formal callback arguments (you can't directly refer to them), they are there in the arguments object, an array-like structure:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments
Take another example
function get( callback ) {
callback( 0, 1, 2 );
}
get( function(a,b,c,d,e) {
});
This time the callback I pass seems to expect more arguments than the caller provides and still, no problem here. Arguments are bound to consecutive call parameters, a will get 0, b will get 1, c will get 2 and d and e will get undefined inside the callback body.
Both examples show that the caller doesn't really care how your callback is defined, whether its number of arguments matches the expectation or not. In case of any mismatch, the worst what could happen is a runtime error:
function get( callback ) {
callback( 0, 1, 2 );
}
get( 1 );
// Uncaught TypeError: callback is not a function
The designer of a function/method decides what arguments it will accept and process. So, if a function accepts a callback as an argument, then it is the design and implementation of the function that decided that and will call the callback at the appropriate time.
It is also the implementer of the function/method that decides what arguments will be passed to the callback when it is called. What confuses many people is that is is the caller of the function that defines the callback function itself that will be called by the main function/method. But the arguments of the callback function MUST be declared to match what the main function/method will pass to the callback. The labels given to the arguments when you define the callback are merely labels for programming convenience (as a means of referring to the arguments by name). How the callback's arguments are defined in the callback function has nothing to do with what is actually passed to the callback - that is all decided by the function/method that calls the callback. So, when you use request.get(), the contract for using it is that it accepts a callback that should be declared to have the arguments (error, response, body) because that's what it will be called with. Now, it is OK to leave off arguments at the end if you aren't going to use them (they will still be there, but you just won't have a convenient name to refer to them by), but you can't leave off arguments before any that you intend to use because order is important.
Who defines that a callback is accepted? The developer of the specific
method?
Yes, the developer of the function/method decides if a callback is accepted.
Also, the 3 parameters that we pass within the function (error,
response, and body)... how does the request module know to populate
these variables with data on return?
The request.get() method is programmed to pass three arguments (error, response, body) to its callback and that's what it will pass. No matter how the callback itself is actually declared, request.get() will pass these three arguments in that order. So, what confuses many people is that the caller of the function/method creates the callback function itself and gets to define the arguments for it. Well, not really. The creator of the callback must create a callback that matches the contract the the function/method is expecting. If it doesn't match the contract, then the callback likely won't function properly as it will get confused about what it was passed. Really the contract here is that the first argument to the callback will be an error value and if that value is not truthy, then the next two arguments will be response and body. Your callback must match that contact in order to use those arguments correctly. Because Javascript is not strictly typed, it will not be a run-time error if you declare your callback incorrectly, but your access to those arguments will likely be wrong - causing things to work incorrectly.
For example, if you declared your callback to be:
function myCallback(response, body, err) { .... }
Then, what your callback sees as response would actually be the error value because request.get() put the error value in the first argument, no matter how the callback itself is declared.
Another ways of seeing this is to define a callback with no defined parameters and then access them entirely with the arguments object.
function myCallback() {
console.log(arguments[0]); // err value
console.log(arguments[1]); // response value
console.log(arguments[2]); // body value
}
The same is true of the return value in the callback. If you are using Array.prototye.map(), it expects a callback that is passed three arguments and returns a new array element. Even though you are implementing the callback, you must define a callback that is compatible with that contract.
This get method accepts a url and a callback. Who defines that a callback is accepted? The developer of the specific method?
Yes. The author(s) of request.get() defined it specifically to expect and make use a "callback" function.
You can define your own functions to accept callbacks as well, especially useful when they depend on other asynchronous functions – such as setTimeout() for a simple example.
function delay(value, callback) {
setTimeout(function () {
// this statement defines the arguments given to the callback
// it specifies that only one is given, which is the `value`
callback(value);
}, 1000);
}
delay('foo', function (value) { // named to match the argument `delay` provides
console.log(value);
});
Also, the 3 parameters that we pass within the function (error, response, and body)... how does the request module know to populate these variables with data on return?
The arguments given and their order are part of request's definition, same as delay() above defining that (value) would be the argument(s) for its callback.
When providing a callback, the parameters only give the arguments names for you own use. They have no effect on how the main function (request.get(), delay(), etc.) behaves.
Even without naming any parameters, request.get() is still passing the same 3 arguments in the same order to the callback:
request.get(url, function () { // no named parameters
var error = arguments[0]; // still the 1st argument at `0` index
var body = arguments[2]; // still the 3rd argument at `2` index
if(error){
console.log('This request resulted in an error', error);
}
console.log(body);
});
I was trying to solve the "Juggling Async" problem in the "learnyounode" workshop from nodeschool.io. I saw a lot of questions here about this problem where it is not working because the url's were being called from a loop. I understand why that wouldn't work.
I had tried something like this.
var http=require('http');
console.log(process.argv[2],process.argv[3],process.argv[4]);
fn(process.argv[2],
fn(process.argv[3],
fn(process.argv[4])));
function fn(url,callback){
http.get(url,function(response){
var string='';
response.setEncoding('utf8');
response.on('data',function(data){
string+=data;
});
response.on('end',function(){
console.log(url,string);
if (callback) {
callback();
}
});
});
};
As per my understanding, the second GET call should go out only after the first one has ended, since it is being initiated after response end. But the output is always in different order.
I have seen the correct solution. I know that doing it this way fails to leverage the advantage of async, but shouldn't the callbacks make it output in order?
When you pass in a function as a callback, you need to only pass in the function name or function definition. By providing the arguments, you are actually calling the function.
E.g. let's say you had a function f1 that took in another function as a parameter, and another function f2 that you want to pass into f1:
function f1(func_param) {
console.log('Executing f1!');
}
function f2(a_param) {
console.log('Executing f2!');
}
When you do the following call (which is similar to what you are doing, providing a callback function and specifying parameters for the callback):
f1(f2(process.argv[2]));
You're evaluating f2 first, so 'Executing f2!' will print first. The return of f2 will get passed as a parameter into f1, which will execute and print 'Executing f1!'
In your call
fn(process.argv[2],
fn(process.argv[3],
fn(process.argv[4])));
You are saying, let's pass the result of fn(process.argv[4]) as a callback to fn(process.argv[3]), and we'll get the result of calling that and pass that as a callback to fn(process.argv[2]).
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 8 years ago.
This question is asked many times in SO. But still I can't get stuff.
I want to get some value from callback. Look at the script below for clarification.
function foo(address){
// google map stuff
geocoder.geocode( { 'address': address}, function(results, status) {
results[0].geometry.location; // I want to return this value
})
}
foo(); //result should be results[0].geometry.location; value
If I try to return that value just getting "undefined". I followed some ideas from SO, but
still fails.
Those are:
function foo(address){
var returnvalue;
geocoder.geocode( { 'address': address}, function(results, status) {
returnvalue = results[0].geometry.location;
})
return returnvalue;
}
foo(); //still undefined
This is impossible as you cannot return from an asynchronous call inside a synchronous method.
In this case you need to pass a callback to foo that will receive the return value
function foo(address, fn){
geocoder.geocode( { 'address': address}, function(results, status) {
fn(results[0].geometry.location);
});
}
foo("address", function(location){
alert(location); // this is where you get the return value
});
The thing is, if an inner function call is asynchronous, then all the functions 'wrapping' this call must also be asynchronous in order to 'return' a response.
If you have a lot of callbacks you might consider taking the plunge and use a promise library like Q.
It makes no sense to return values from a callback. Instead, do the "foo()" work you want to do inside your callback.
Asynchronous callbacks are invoked by the browser or by some framework like the Google geocoding library when events happen. There's no place for returned values to go. A callback function can return a value, in other words, but the code that calls the function won't pay attention to the return value.
If you happen to be using jQuery, you might want to give this a shot:
http://api.jquery.com/category/deferred-object/
It allows you to defer the execution of your callback function until the ajax request (or any async operation) is completed. This can also be used to call a callback once several ajax requests have all completed.