Angular httpclient.get does returns undefined - angular7

I have the following code which prints "undefined" to the console
let f:Observable<Asset[]>;
f= this.http.get<HttpResponse<Asset[]>>(this.baseApiUrl+"Asset",this.httpNormalOptions).pipe(map(
response=>{
return response.body;
}
))
f.subscribe(m=>{console.log(m)});
return f;
However the code I had before worked fine
return this.http.get<Asset[]>(this.baseApiUrl+"Asset",this.httpNormalOptions).pipe(map(
response=>{
return response;
}
))
The headers for both are exactly the same as follows
this.httpNormalOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + this.auth_token,
observe:'response'
})
}
Why does one of these return "undefined" while the other returns a populated array? I have checked on the webservice side and a populated array is being returned in both cases.

let f:Observable<Asset[]>;
f= this.http.get<Asset[]>(this.baseApiUrl+"Asset",this.httpNormalOptions).pipe(map(
response:= Asset[]>{
return response;
}
))
f.subscribe(m=>{console.log(m)});
return f;

Related

how to display a file using react-native

So, I have those "cards" to which are attached files.
I want to be able to display the content of these files (when possible; I do not expect to show binary files obviously, but text, pdf, images,...) to the user.
Upon a longPress on an attachment, the openAttachment() function is be called. That function downloads the file from the server if necessary and then (tries to) open it:
// Opens an attachment
const openAttachment = async (attachment) => {
try {
// Download file if not already done
const fileInfo = await FileSystem.getInfoAsync(FileSystem.cacheDirectory + attachment.name)
let uri
if (!fileInfo.exists) {
console.log('Downloading attachment')
resp = await FileSystem.downloadAsync(
server.value + `/index.php/apps/deck/api/v1.0/boards/${route.params.boardId}/stacks/${route.params.stackId}/cards/${route.params.cardId}/attachments/${attachment.id}`,
FileSystem.cacheDirectory + attachment.name,
{
headers: {
'Authorization': token.value
},
},
)
console.log(resp)
uri = await FileSystem.getContentUriAsync(resp.uri)
} else {
console.log('File already in cache')
uri = await FileSystem.getContentUriAsync(fileInfo.uri)
}
console.log('Opening file ' + uri)
Sharing.shareAsync(uri);
} catch {
Toast.show({
type: 'error',
text1: i18n.t('error'),
text2: error.message,
})
console.log(error)
}
}
The issue always arrise at the Sharing.shareAsync(uri); line: Whatever I put there, it fails:
Sharing.shareAsync(uri) does not seem to be supported on my platform: https://docs.expo.dev/versions/latest/sdk/sharing/
Linking.openURL(uri) does not support the file:// scheme (the uri is in the form file:///var/mobile/Containers/Data/Application/5C1CB402-5ED1-4E17-B907-46111AE3FB7C/Library/Caches/test.pdf)
await WebBrowser.openBrowserAsync(uri) (from expo-web-browser) does not seem to be able to open local files
How am I supposed to do to display those files? Anyone has an idea?
Cyrille
I found a solution using react-native-file-viewer
// Opens an attachment
const openAttachment = async (attachment) => {
try {
// Download file if not already done
const fileInfo = await FileSystem.getInfoAsync(FileSystem.cacheDirectory + "attachment.name")
let uri
if (!fileInfo.exists) {
console.log('Downloading attachment')
const resp = await FileSystem.downloadAsync(
server.value + `/index.php/apps/deck/api/v1.0/boards/${route.params.boardId}/stacks/${route.params.stackId}/cards/${route.params.cardId}/attachments/${attachment.id}`,
FileSystem.cacheDirectory + attachment.name,
{
headers: {
'Authorization': token.value
},
},
)
console.log(resp)
uri = await FileSystem.getContentUriAsync(resp.uri)
} else {
console.log('File already in cache')
uri = await FileSystem.getContentUriAsync(fileInfo.uri)
}
console.log('opening file', uri)
FileViewer.open(uri)
} catch(error) {
Toast.show({
type: 'error',
text1: i18n.t('error'),
text2: error.message,
})
console.log(error)
}
}

getting current result from method inside another method

am trying to call a method which calls another method .. and depending on that method result i will continue with my method .. something like this:
void submit() async{
if (login) {
....
bool result = await Login("966" + phone, _data.code);
if (result) {
successpage();
} else {
.....
}
and login:
bool Login(String phone, String SMScode) {
http.post(baseUrl + loginURL + "?phone=" + phone + "&smsVerificationCode="+ SMScode,
headers: {
'content-type': 'application/json'
}).then((response) {
final jsonResponse = json.decode(Utf8Codec().decode(response.bodyBytes));
print("LOGIN: " + jsonResponse.toString());
Map decoded = json.decode(response.body);
print(decoded['success']);
if (decoded['success']) {
globals.token = decoded['token'];
globals.login = true;
}else{
globals.login = false;
}
});
return globals.login;
}
but this doesn't work and doesn't give me the result of the last bool i need .. how to solve this?
The asynchronous handling is incorrect in your program. Basically your Login function returns without waiting the http post.
The following update should work.
Future<bool> Login(String phone, String SMScode) async {
final response = await http.post('$baseUrl$loginURL?phone=$phone&smsVerificationCode=$SMScode',
headers: {'content-type': 'application/json'});
final jsonResponse = json.decode(Utf8Codec().decode(response.bodyBytes));
print("LOGIN: " + jsonResponse.toString());
Map decoded = json.decode(response.body);
print(decoded['success']);
if (decoded['success']) {
globals.token = decoded['token'];
globals.login = true;
} else {
globals.login = false;
}
return globals.login;
}

How do I asyncronously build an array of data?

List responseJson;
List eventDetails = [];
Future<String> fetchPost() async {
final response = await http.get(
"https..",
headers: {
HttpHeaders.AUTHORIZATION:
"Bearer ..."
});
for(var i = 0; i< (responseJson?.length ?? 0);i++) {
final eventDetailsResponse = await http.get(
"https:.." + responseJson[i]["id"].toString(),
headers: {
HttpHeaders.AUTHORIZATION:
"Bearer .."
});
eventDetails.add(json.decode(eventDetailsResponse.body));
}
this.setState(() {
responseJson = json.decode(response.body);
print(eventDetails);
print(responseJson);
});
Hi there! I have an array defined, I filled the array in with elements, each element is the result of an API call, and then I use the function this.setState to trigger the list view to update, on the first run eventDetails is empty, however on the second run it gets filled in with data, how can I make it await?
Thank you in advance.
Are you trying to populate your view from a future?
If that's the case, have a look at FutureBuilder.

Null while returning a Future in Dart

I have two classes, a user_api_manager and a base_api_manager. From user_api_manager i call the get method of base_api_manager which performs an http get request and returns a Future<String>. The getrequest is performed but i am not pass the result to my user_api_manager class. The callback result is always null.
This is my user_api_manager.dart
static Future<Map<String,dynamic>> forgotPasswordAPI(String email) async{
String url = Constants.BASE_URL + Constants.FORGOT_PASSWORD_URL + email;
await BaseApiManager.get(url: url).then((val) {
var response = JSON.decode(val);
var status = response['status'];
String message = '';
print(response);
switch (response['status']) {
case Constants.SUCCESS:
message = Constants.SUCCESS_RESPONSE;
break;
case Constants.SERVER_ERROR:
message = Constants.SERVER_ERROR_MESSAGE;
break;
case Constants.UNAUTHORISED:
message = Constants.UNAUTHORISED_MESSAGE;
break;
}
return {'status':status,'message':message};
});
}
and here is my base_api_manager.dart
static Future<String> get({url : String,
parameters : Map ,
headers: Map }) async {
var client = new http.Client();
Map<String,dynamic> resultJSON;
final c = new Completer();
await client.get(url).then((response) { //response is always null
resultJSON = {
'status' : response.statusCode,
'body' : JSON.decode(response.body)
};
c.complete(resultJSON.toString());
return c.future;
});
}
How to solve this issue?
Move the return c.future outside of the response processing, i.e you want to return this from your get otherwise you will return null.
You can simplify the code. That should make it easier to locate the problem
static Future<String> get({url : String, parameters : Map, headers: Map }) async {
var client = new http.Client();
final response = await client.get(url);
print(response.body);
var resultJSON = {
'status' : response.statusCode,
'body' : JSON.decode(response.body)
};
return resultJSON.toString()
}
What does that code print?

Making a POST request to Tumblr's API inside a Chrome Extension

I'm trying to make a text post to Tumblr using their API and chrome_ex_oauth.
API: http://www.tumblr.com/docs/en/api/v2#posting
chrome_ex_oauth: http://code.google.com/chrome/extensions/tut_oauth.html
The whole process of getting authorized works. What I can't get to work is doing a POST. I'm doing the following:
Edit: I've updated the code to reflect Rob W's correct suggestion about the body field
var stringify = function (parameters) {
var params = [];
for(var p in parameters) {
params.push(encodeURIComponent(p) + '=' +
encodeURIComponent(parameters[p]));
}
return params.join('&');
};
var onAuthorized = function() {
var url = 'http://api.tumblr.com/v2/blog/jindie.tumblr.com/post';
var request = {
'method': 'POST',
'headers':{
'Content-Type':'application/x-www-form-urlencoded'
},
'body': stringify({
'type': 'text',
'state': 'draft',
'title': 'Test post...',
'body': 'Hello, World!'
})
};
oauth.sendSignedRequest(url, function(responseText, xhr){alert(responseText);}, request);
};
oauth.authorize(onAuthorized);
I've been examining the code, and thinking what could be wrong, but I seriously have no idea. Do you?
Do you know where I'm going wrong?
When the documentation doesn't help have a look at the source code, chrome_ex_oauth.js.
You have to use 'body' instead of 'parameters':
var request = {
'method': 'POST',
'body': {
Debugging
In order to find the cause, I followed these steps (annotated my thoughts):
Apparently, the post body is empty. So, the implementation of the API must be wrong.
Ctrl + F sendSignedRequest:
ChromeExOAuth.prototype.sendSignedRequest = function(url, callback, opt_params) {
var method = opt_params && opt_params['method'] || 'GET';
var body = opt_params && opt_params['body'] || null;
var params = opt_params && opt_params['parameters'] || {};
var headers = opt_params && opt_params['headers'] || {};
var signedUrl = this.signURL(url, method, params);
// Hmm...? Where is `params` being passed...?
ChromeExOAuth.sendRequest(method, signedUrl, headers, body, function (xhr) {
if (xhr.readyState == 4) {
callback(xhr.responseText, xhr);
}
});
};
signURL doesn't modify params, so that's not a problem.
Ctrl + F sendRequest:
ChromeExOAuth.sendRequest = function(method, url, headers, body, callback) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(data) {
callback(xhr, data);
}
xhr.open(method, url, true);
if (headers) { . . . }
xhr.send(body); // <-- !!!
};
Got it! body has to be used instead of parameters.
Backtracks the body variable to the request['body'] (see 2).

Resources