ionic 2, "return" is not working - return

tamGetir(yno){
let yazilan:any;
let body={
uyeno:this.uye.uyeno,
eposta: this.uye.eposta,
sifre: this.uye.sifre,
gunlukno: this.defterno,
yazino: yno
}
this.http.post('http://www.gibigo.com/sayfalar/ion_android_gungetir2.php',JSON.stringify(body))
.map(res=>res.json())
.subscribe(data=>{
console.log(data.yazi);
yazilan=data.yazi;
});
return yazilan;
}
"data.yazi" looks correct in console, but return operation does not work. Return is undifinied. How can i return it correct.

The http function returns an Observable. This is asynchrounous. When you use subscribe, the http request is fired and an observable is returned. The data is received on response.
yazilan=data.yazi; is happening after the return statement.
You should use a class variable to simply save the data within the subscription.
If your method is in a provider, return the http call with map and subscribe in your component
tamGetir(yno){
let yazilan:any;
let body={
uyeno:this.uye.uyeno,
eposta: this.uye.eposta,
sifre: this.uye.sifre,
gunlukno: this.defterno,
yazino: yno
}
return this.http.post('http://www.gibigo.com/sayfalar/ion_android_gungetir2.php',JSON.stringify(body))
.map(res=>res.json())
In your component:
yazi:any;//class variable
callHttpFunction(){
this.provider.tamGetir(yno)
.subscribe(data=>{//call the subsribe
console.log(data);
this.data_variable =data.yazi;
})
}

Related

Manifest v3 extension: asynchronous event listener does not keep the service worker alive [duplicate]

I am trying to pass messages between content script and the extension
Here is what I have in content-script
chrome.runtime.sendMessage({type: "getUrls"}, function(response) {
console.log(response)
});
And in the background script I have
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
if (request.type == "getUrls"){
getUrls(request, sender, sendResponse)
}
});
function getUrls(request, sender, sendResponse){
var resp = sendResponse;
$.ajax({
url: "http://localhost:3000/urls",
method: 'GET',
success: function(d){
resp({urls: d})
}
});
}
Now if I send the response before the ajax call in the getUrls function, the response is sent successfully, but in the success method of the ajax call when I send the response it doesn't send it, when I go into debugging I can see that the port is null inside the code for sendResponse function.
From the documentation for chrome.runtime.onMessage.addListener:
This function becomes invalid when the event listener returns, unless you return true from the event listener to indicate you wish to send a response asynchronously (this will keep the message channel open to the other end until sendResponse is called).
So you just need to add return true; after the call to getUrls to indicate that you'll call the response function asynchronously.
The accepted answer is correct, I just wanted to add sample code that simplifies this.
The problem is that the API (in my view) is not well designed because it forces us developers to know if a particular message will be handled async or not. If you handle many different messages this becomes an impossible task because you never know if deep down some function a passed-in sendResponse will be called async or not.
Consider this:
chrome.extension.onMessage.addListener(function (request, sender, sendResponseParam) {
if (request.method == "method1") {
handleMethod1(sendResponse);
}
How can I know if deep down handleMethod1 the call will be async or not? How can someone that modifies handleMethod1 knows that it will break a caller by introducing something async?
My solution is this:
chrome.extension.onMessage.addListener(function (request, sender, sendResponseParam) {
var responseStatus = { bCalled: false };
function sendResponse(obj) { //dummy wrapper to deal with exceptions and detect async
try {
sendResponseParam(obj);
} catch (e) {
//error handling
}
responseStatus.bCalled= true;
}
if (request.method == "method1") {
handleMethod1(sendResponse);
}
else if (request.method == "method2") {
handleMethod2(sendResponse);
}
...
if (!responseStatus.bCalled) { //if its set, the call wasn't async, else it is.
return true;
}
});
This automatically handles the return value, regardless of how you choose to handle the message. Note that this assumes that you never forget to call the response function. Also note that chromium could have automated this for us, I don't see why they didn't.
You can use my library https://github.com/lawlietmester/webextension to make this work in both Chrome and FF with Firefox way without callbacks.
Your code will look like:
Browser.runtime.onMessage.addListener( request => new Promise( resolve => {
if( !request || typeof request !== 'object' || request.type !== "getUrls" ) return;
$.ajax({
'url': "http://localhost:3000/urls",
'method': 'GET'
}).then( urls => { resolve({ urls }); });
}) );

Handle Mono.empty() in GatewayFilter

I'm building a GatewayFilter, but I'm having problems handling cases where I don't have data. Here is a sample of the GatewayFilterFactory<>:
return (exchange, chain) -> getDataFromRedis()
.flatMap(redisData -> {
ServerHttpRequest request = exchange.getRequest().mutate()
.header("header", redisData).build();
return chain.filter(exchange.mutate().request(request).build());
});
Here is the getDataFromRedis method:
Mono<String> getDataFromRedis() {
return redis.get("key");
}
It returns a Mono with a String value, or empty if it wasn't found.
The above example works as expected, but when the data is redis is not found, and an empty Mono is returned, then I need it to return a redirect. So this is my attempt:
return (exchange, chain) -> getDataFromRedis()
.flatMap(redisData -> {
ServerHttpRequest request = exchange.getRequest().mutate()
.header("header", redisData).build();
return chain.filter(exchange.mutate().request(request).build());
})
.switchIfEmpty(Mono.defer(() -> {
exchange.getResponse().setStatusCode(HttpStatus.FOUND);
exchange.getResponse().getHeaders().add(HttpHeaders.LOCATION, "some other url");
return exchange.getResponse().setComplete();
}));
The deferred mono in switchIfEmpty is always invoked, irrespective of whether there is data in redis or not.
To summarise, I need the filter to add a header value it gets from Redis, but redirect if there is no data available.

Zapier JS Action to Fetch Klout Scores

I'm trying to create a Java Script Code Action on Zapier to fetch Klout Scores for any given Twitter user name...
I've realized that this needs to be done in 2 stages:
1) First get the Klout ID for any Twitter screen_name:
http://api.klout.com/v2/identity.json/twitter?screenName="+screen_name+"&key="+klout_apikey"
Klout replies back to that with JSon:
{"id":"85568398087870011","network":"ks"}
2) second get the Klout score for that Klout id:
http://api.klout.com/v2/user.json/"+klout.id+"/score?key="+klout_apikey"
Klout replies back to this with JSon:
{"score":65.68382904221806,"scoreDelta":{"dayChange":-0.03663891859041257,"weekChange":-0.5495711661078815,"monthChange":-1.4045672671990417},"bucket":"60-69"}
Of course, what I need is the "score":65.68382904221806 object of the JSon reply array.
I use these following JS functions proposed by #KayCee:
var klout_apikey = '<my klout api key>';
fetch("http://api.klout.com/v2/identity.json/twitter?screenName="+screen_name+"&key="+klout_apikey")
.then(function(res) {
return res.json();
})
.then(function(klout) {
console.log(klout);
if(klout.id) {
return fetch("http://api.klout.com/v2/user.json/"+klout.id+"/score?key="+klout_apikey")
}
}).then(function(res) {
return res.json();
}).then(function(body) {
// console.log(body.score);
//Here is where you are telling Zapier what you want to output.
callback(null, body.score)
}).catch(callback); //Required by Zapier for all asynchronous functions.
In the "input data" section of the Zapier code action i pass the screen_name as a variable:
screen_name: [the twitter handle]
What I get back is the following error message:
SyntaxError: Invalid or unexpected token
What is the error that you see? You could do this by simply using the fetch client. You might want to remove the variable declarations before adding this to the code step.
var inputData = {'screen_name': 'jtimberlake'}
//Remove the line above before pasting in the Code step. You will need to configure it in the Zap.
var klout_apikey = '2gm5rt3hsdsdrzgvnskmgm'; //Not a real key
fetch("http://api.klout.com/v2/identity.json/twitter?screenName="+inputData.screen_name+"&key="+klout_apikey)
.then(function(res) {
return res.json();
})
.then(function(body) {
console.log(body);
if(body.id) {
return fetch("http://api.klout.com/v2/user.json/"+body.id+"/score?key="+klout_apikey)
}
}).then(function(res) {
return res.json();
}).then(function(body) {
console.log(body);
//Here is where you are telling Zapier what you want to output.
callback(null, body)
}).catch(callback); //Required by Zapier for all asynchronous functions.
Refer to their documentation here - https://zapier.com/help/code/#introductory-http-example
Also refer to their Store client which allows you to store values (for cache) - https://zapier.com/help/code/#storeclient-javascript

How to handle if else in Dart Future

I need to get Google Drive a folder's fileId. If the folder does not exist, I need to create a folder with that name and return fileId. With fileId, I need to do other works.
The Google Drive API in Dart is ok for me, I can create a folder with Dart. The question is about Future.
The code is as follow:
drive.files.list(q:"title='TEST'").then((result){
if(result.items.length == 0) {
driveclient.File file = new driveclient.File.fromJson({"title":"TEST", "mimeType": "application/vnd.google-apps.folder"});
drive.files.insert(file).then((result2) {
return result2.id;
});
} else {
return result.items[0].id;
}
});
When TEST exists, the id is returned. But if TEST doesn't, the function error because no return.
How to do that?
Thanks in advance.
You need to return the future from the then method you call in line 4:
drive.files.list(q:"title='TEST'").then((result){
if(result.items.length == 0) {
driveclient.File file = new driveclient.File.fromJson({"title":"TEST", "mimeType": "application/vnd.google-apps.folder"});
return drive.files.insert(file).then((result2) {
return result2.id;
});
} else {
return result.items[0].id;
}
});
then() returns a new future there completes with the value returned from the method you give as parameter to the method. then() is also smart enough to resolve all nested future's so you will always handle a value inside a then() method and never a instance of Future.

Handle POST data using Dart Route after already listening to stream

I am using route to handle http requests to my server. This is my current route code:
HttpServer.bind("127.0.0.1", 8080).then((server) {
new Router(server)
..filter(new RegExp(r'/.*'), addCorsHeaders)
..filter(new RegExp(r'/admin/.*'), authenticate)
..serve(userGetURL, method: 'GET').listen(userGetHandler)
..serve(userPostURL, method: 'POST').listen(userPostHandler);
});
I am trying to get JSON data that I am POSTing to a URL. The data will be used to get an entity from the database and return it as JSON to the caller. I am basically trying to create a server application that will handle all the data and a client application that will display it.
I cannot figure out how to get the data from a POST. Everything I have tried requires that I listen to the stream, but it is already being listened to. This is how I have been trying to get the POST data:
userPostHandler(HttpRequest req) {
req.listen((List<int> buffer) {
// Return the data back to the client.
res.write(new String.fromCharCodes(buffer));
res.close();
}
}
The problem is I get a Bad state: Stream has already been listened to. error.
EDIT: The filters
Future<bool> authenticate(HttpRequest req) {
if (req.method == 'POST') {
// Post data is not null
// Authenticate user
String userName = '';
String password = '';
User user = new User();
user.DBConnect().then((User user) {
return new Future.value(user.ValidateUser(userName, password));
});
}
}
Future<bool> addCorsHeaders(HttpRequest req) {
print('${req.method}: ${req.uri.path}');
req.response.headers.add('Access-Control-Allow-Origin', '*, ');
req.response.headers.add('Access-Control-Allow-Methods', 'POST, OPTIONS, GET');
req.response.headers.add('Access-Control-Allow-Headers',
'Origin, X-Requested-With, Content-Type, Accept');
return new Future.value(true);
}
I have never used the Route package but I wonder why you want to listen inside the Handler. Can't you just access the properties you want to process?
Otherwise you could try
req.asBroadcastStream().listen(...)
A BroadcastStream supports multiple listeners.
More information in this article Use Streams for Data
Using the following code I was able to get a POST working:
void main() {
HttpServer.bind("127.0.0.1", 8080).then((server) {
new Router(server)
..filter(new RegExp(r'/.*'), addCorsHeaders)
..filter(new RegExp(r'/admin/.*'), authenticate)
..serve(userGetURL, method: 'GET').listen(userGetHandler)
..serve(userPostURL, method: 'POST').listen(userPostHandler);
});
}
Future userPostHandler(HttpRequest req) {
bool headerSent = false;
// Start listening before writing to the response.
req.listen((List<int> buffer) {
if (!headerSent) {
req.response.write("User POST");
headerSent = true;
}
req.response.write(new String.fromCharCodes(buffer));
},
// Use onDone to close the response.
onDone: () => req.response.close()
);
}
Here is what I figured out. Any write to the response automatically drains the body and thus destroy the POST data. As mentioned here. Also, listening to the response is done asynchronously and thus must be completed before close() is called.

Resources