I have a function that has an observable object and I need to return the value of the fetch that I use in this function. But I don't know why I can not return the result when I display the result it is totally fine but when I try to return it is empty.
I check a few similar problems but they were very complex and also they didn't match my case and also after trying one or two of them still the problem exists.
function getRandomQuote() {
const obs$ = Observable.create(async(observer) => {
const result = await fetch(RANDOM_QUOTE_API_URL)
.then(Response => Response.json())
.then(data => data.content)
observer.next(result)
console.log(result)
})
return obs$.subscribe(x => { return x })
}
I tried to use return only inside the subscribe part but it doesn't work and in one of the similar cases they tried to return the outer part which I tried and still not work
I am new with observable and JavaScrip I just need to return this value and use it in another function.
thank you
You should return Observable other than Subscription
function getRandomQuote() {
return Observable.create(async(observer) => {
const result = await fetch(RANDOM_QUOTE_API_URL)
.then(Response => Response.json())
.then(data => data.content)
observer.next(result)
})
}
//usage
getRandomQuote().subscribe(console.log)
Or there is defer() and from() operator which helps you convert promise to observable
getRandomQuote=()=>defer(()=>from(fetch(RANDOM_QUOTE_API_URL)
.then(Response => Response.json())
.then(data => data.content))
//usage
getRandomQuote().subscribe(console.log)
Related
What method is there without using setTimeout() to allow data from the fetch to be stored in the stored_data array, then allowing the test function to manipulate.
So far i get undefined.
let stored_data = []
fetch('https://jsonplaceholder.typicode.com/todos/1')
.then(response => response.json())
.then(json => stored_data.push(json))
function test(e) {
console.log(e)
}
You could simply chain another .then. You also forgot to declare store_data as a variable
let stored_data = []
fetch('https://jsonplaceholder.typicode.com/todos/1')
.then(response => response.json())
.then(json => stored_data.push(json))
.then( _ => {
// array now ready for manipulation
})
I want to fetch data for every object in an array and return an array of new objects with the previous and newly fetched data.I got stucked on getting my result array as my function is returning an array of resolved undefined promises.
I am using a flight search api thats using the apca function for fetching
export const searchApcaLocation = async (dataArr,setDeals) => {
const promises = await dataArr.map(async item => {
apca.request(item.destination);
apca.onSuccess = (data) => {
return fetch('http://localhost:3050/googlePlaceSearch',{
method:"post",
headers:{'Content-Type':'application/json'},
body:JSON.stringify({
cityName:data.airports[0].city
})
})
.then(res => res.json())
.then(imagelinkData => {
const locationObject = {
data: item,
imagelink: imagelinkData.link
}
return locationObject
})
.catch(err => console.log('error on image search',err))
};
apca.onError = (data) => {
console.log('error',data)
};
})
const results = await Promise.all(promises)
return results
}
can someone guide me please on what am I doing wrong?
edit:
as I am trying to fix it realized the problem is I am not returning anything in my map function but if trying to return the apca.onSuccess I am getting an array of functions
just return is missing before fetch function. since you're not returning your promise result it's giving undefined.
export const searchApcaLocation = async (dataArr,setDeals) => {
const promises = await dataArr.map(async item => {
apca.request(item.destination);
apca.onSuccess = (data) => {
return fetch('http://localhost:3050/googlePlaceSearch',{
method:"post",
headers:{'Content-Type':'application/json'},
body:JSON.stringify({
cityName:data.airports[0].city
})
})
.then(res => res.json())
.then(imagelinkData => {
const locationObject = {
data: item,
imagelink: imagelinkData.link
}
return locationObject
})
.catch(err => console.log('error on image search',err))
};
apca.onError = (data) => {
console.log('error',data)
};
})
const results = await Promise.all(promises)
return results
}
The issue in your case might be, that you are using async/await and then blocks together.
Let me sum up what is happening :
1) you await dataArray.map
2) within the map callback, you use the onSuccess method of apca
3) within this method you are using then blocks which won't await until you got a response.
At this point where you return the locationObject, your function already reached the return statement and tries to return results.
But results are of course undefined because they never get resolved at all.
Also, keep in mind that your function returns another promise because you used async/await which you have to resolve where you imported it.
Cheers :)
This is a silly question but can you explain what is wrong with this code?
Why can't I perform this?
const fetch = require('node-fetch');
const fetchProm = (() => {
return fetch('https://api.github.com/users/github');
}).then((response) => {
return response.json();
}).then((json) => {
console.log(json)
});
Declaring a function is not the same as calling one
You are not calling the function that returns the promise, just declaring it. You'll need to add an additional set of parentheses before the first .then() in order to actually call the function:
const fetch = require('node-fetch');
const fetchProm = (() => {
return fetch('https://api.github.com/users/github');
})().then((response) => {
return response.json();
}).then((json) => {
console.log(json)
});
If you want to call everything at a later time, you need to place the whole thing in its own function where the promises get handled in an isolated scope:
const fetch = require('node-fetch');
const fetchProm = () => {
fetch('https://api.github.com/users/github')
.then(response => response.json())
.then(json => console.log(json));
};
fetchProm();
I need to call multiple endpoints with each call dependent on the results of the previous call.
return http.get('url1')
.then(response1 => {
return response1.data
})
.then(data => {
http.get('url2' + data)
.then(response2 => {
return response2.data
}) // etc ... until the 'nth url'
})
It can get quite nested. Is there a way to flatten this, maybe using generators?
Promises are made for flattening:
return http.get('url1').then(response1 => {
return response1.data
}).then(data => {
return http.get('url2' + data);
}).then(response2 => {
return http.get('url3' + response2.data);
}) // ...etc
If your JavaScript engine supports async/await, this can be made shorter and more readable within an async function:
async function demo() {
const response1 = await http.get('url1');
const response2 = await http.get('url2' + response1.data);
const response3 = await http.get('url3' + response2.data);
// ...
return responseN;
}
... and then call that:
demo().then(response => {
console.log(response);
// ...etc
});
I don't know that there's a great solution to avoid the string of then(), but ou don't need to nest:
return http.get('url1')
.then(response1 => response1.data)
.then(data => http.get('url2' + data))
.then(response2 => response2.data )
// etc ... until the 'nth url'
If the pattern is the same in every case, you may be able to pass a list of urls and use reduce()
Flatten promise-chains by returning whenever you have a new promise. However, when you have a non-promise value, don't. It just wastes of a micro-task. Just use the value directly instead:
return http.get('url1')
.then(response => http.get('url2' + response.data))
.then(response => doSomethingWith(response.data))
To get a simple data variable name, use destructuring instead:
return http.get('url1')
.then(({data}) => http.get('url2' + data))
.then(({data}) => doSomethingWith(data))
I'm having some issues understanding variables and functions using fetch.
I'm trying to pass the value of response from
.then(response => response.json())
to
.then(lang => response['lang'].slice(-2)
But I am getting the undefined variable response error, so I'm not referencing the variable correctly. What's the correct way of calling it?
Also I want to call both console logs, the piece of code below currently does that but I don't think I should be overwriting response function, can I call a function without arguments or the commands by themselves?
.then(response => console.log(response['text']) & console.log(food))
console.log(response['text']) & console.log(food)
fetch("https://localhost:8000", {method:"POST", body:fd})
.then(response => response.json())
.then(lang => response['lang'].slice(-2))
.then(food => "Temporary")
.then(function detectType(lang) {
switch(lang) {
case 'abc':
food = "Bananas";
break;
case 'def':
food = "Apples";
break;
default:
food = "Bananas";
break;
}})
.then(response => console.log(response['text']) & console.log(food))
.catch(err => console.error(err));
}
If I'm understanding what you want to do, keep in mind that the return value of one function is the state received by the next function. So you'd be looking to do something more like this:
fetch("https://localhost:8000", {method:"POST", body:fd})
.then(response => response.json())
.then(response => {
response['lang'] = response['lang'].slice(-2);
return response;
})
.then(response => {
response['food'] = "Temporary";
return response;
})
.then(function detectType(response) {
switch(response['lang']) {
case 'abc':
response['food'] = "Bananas";
break;
case 'def':
response['food'] = "Apples";
break;
default:
response['food'] = "Bananas";
break;
}
return response;
})
.then(response => {
console.log(response['text']);
console.log(response['food']);
})
.catch(err => console.error(err));
}
Regarding fetch(), remember that it is very 'Promise heavy'.
fetch("https://localhost:8000", {method:"POST", body:fd}) returns a Promise, which you handle with the first then()
then(response => response.json()) returning response.json() will give you the state of response.json() in the next .then(). So, you have access to the JSON representation of the response by the next then().
Let's take a look at how it should look:
fetch("https://localhost:8000", {method:"POST", body:fd})
.then(response => response.json())
.then(jsonResp => jsonResp['lang'] );
By that last line, you can check the JSON object and its keys without going down a Promise chain. If you want to check the lang attribute, you have access to it the way it's seen on the example.
Hope this helps!