This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 7 years ago.
I'm trying to make a function that returns the body of an api call using a promise. My code is
function checkApi(link) {
var promise = new Promise(function(resolve, reject) {
//query api
});
promise.then(function(value) {
console.log(value); //want to return this, this would be the body
}, function(reason) {
console.log(reason); //this is an error code from the request
});
}
var response = checkApi('http://google.com');
console.log(response);
Instead of doing console log, I want to return the body of google.com so that I can use it. This is just a scope problem, but I'm not sure how to fix it. Thanks,
You can return the promise and then when you call the checkApi you can attach another .then().
function checkApi(link) {
var promise = new Promise(function(resolve, reject) {
//query api
});
return promise.then(function(value) {
console.log(value); //Here you can preprocess the value if you want,
//Otherwise just remove this .then() and just
return value; //use a catch()
}, function(reason) {
console.log(reason); //this is an error code from the request
});
}
//presuming this is not the global scope.
var self = this;
checkApi('http://google.com')
.then(function (value){
// Anything you want to do with this value in this scope you have
// to do it from within this function.
self.someFunction(value);
console.log(value)
});
Related
This question already has answers here:
Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference
(7 answers)
Closed 5 months ago.
I want to get a value from chrome.storage.local
var storage = chrome.storage.local;
authToken = storage.get('logintoken', function(result) {
var channels = result.logintoken;
authToken=result.logintoken;
console.log(authToken);
return authToken;
});
alert(authToken);
but out of the function authToken is undefined.
function getAllStorageSyncData(top_key) {
// Immediately return a promise and start asynchronous work
return new Promise((resolve, reject) => {
// Asynchronously fetch all data from storage.sync.
chrome.storage.local.get(top_key, (items) => {
// Pass any observed errors down the promise chain.
if (chrome.runtime.lastError) {
return reject(chrome.runtime.lastError);
}
// Pass the data retrieved from storage down the promise chain.
resolve(items);
});
});
}
Used this method and await like
var obj = await getAllStorageSyncData(['logintoken']);
and its worked
https://stackoverflow.com/a/72947864/1615818
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 4 years ago.
I'm trying to use a promise in my function but it never returns. This is my code:
function getData(id) {
return new Promise(function(resolve, reject) {
DbUtil.connection.query("my query... ", [id],
function (error, results, fields) {
if (error) {
reject(error);
} else {
resolve(results);
}
}
);
})
}
The query works and I can see its results in the else block. But the function itself doesn't return. I tried adding a return statement after the resolve, and also after the Promise function itself. But it still doesn't return.
What am I missing?
EDIT: how do I know the function doesn't return? Because
function main() {
var data = getData(1);
console.log("data returned? " + data);
}
in the above main function the log statement is never called.
It's not the proper way to handle a promise
Try this:
var data;
getData(1).then(function(d) {
console.log(d);
data = d;
});
// Since a Promise is async, you can't log data here
or
async function main() {
var data = await getData(1);
console.log(data);
}
Note that this examples does not handle catch case.
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 4 years ago.
I am using this native script firebase plugin, which makes me use this function:
getValue() {
var value;
firebase.getValue('/companies')
.then(result => {
console.log(JSON.stringify(result));
value = result;
return result;
})
.catch(error => {
console.log("Error: " + error);
return error;
});
return value;
}
If I import it in another file and use it like this:
var myValue = this.myFirebaseService.getValue();
If I run it the first time it returns undefined but the second time it returns the value.
My question is how do I make the firebase function return a promise so I can make my second statement wait for it.
The firebase function you're referring to is returning a promise. That's why you can use .then and .catch after calling the getValue function.
If you return the firebase promise from getValue(), like this:
getValue(){
return firebase.getValue('/companies');
}
You'll be able to call getValue() whenever you like, but you'll have to execute the code after getValue() (which is a promise) is resolved. Like so:
getValue().then(function(value) {
console.log(value);
});
I would read up on promises if you don't understand this: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
You can initialize myValue after the result has been received from the then block.
Something like this:
var myValue;
function getValue() {
return firebase.getValue('/companies');
}
myValue = getValue().then(result => {
const value = JSON.stringify(result);
console.log(value);
return value;
})
.catch(error => {
console.log("Error: " + error);
});
}
This question already has answers here:
How to know when all Promises are Resolved in a dynamic "iterable" parameter?
(5 answers)
Closed 6 years ago.
I've got an api call that sometimes returns paged responses. I'd like to automatically add these to my promises so I get the callback once all the data has arrived.
This is my attempt. I'd expect the new promise to be added and Promise.all to resolve once that is done.
What actually happens is that Promise.all doesn't wait for the second request. My guess is that Promise.all attaches "listeners" when it's called.
Is there a way to "reintialize" Promise.all()?
function testCase (urls, callback) {
var promises = [];
$.each(urls, function (k, v) {
promises.push(new Promise(function(resolve, reject) {
$.get(v, function(response) {
if (response.meta && response.meta.next) {
promises.push(new Promise(function (resolve, reject) {
$.get(v + '&offset=' + response.meta.next, function (response) {
resolve(response);
});
}));
}
resolve(response);
}).fail(function(e) {reject(e)});
}));
});
Promise.all(promises).then(function (data) {
var response = {resource: []};
$.each(data, function (i, v) {
response.resource = response.resource.concat(v.resource);
});
callback(response);
}).catch(function (e) {
console.log(e);
});
}
Desired flow is something like:
Create a set of promises.
Some of the promises spawn more promises.
Once all the initial promises and spawned promises resolve, call the callback.
It looks like the overall goal is:
For each entry in urls, call $.get and wait for it to complete.
If it returns just a response without "next", keep that one response
If it returns a response with a "next," we want to request the "next" as well and then keep both of them.
Call the callback with response when all of the work is done.
I would change #2 so you just return the promise and fulfill it with response.
A key thing about promises is that then returns a new promise, which will be resolved based on what you return: if you return a non-thenable value, the promise is fulfilled with that value; if you return a thenable, the promise is resolved to the thenable you return. That means that if you have a source of promises ($.get, in this case), you almost never need to use new Promise; just use the promises you create with then. (And catch.)
(If the term "thenable" isn't familiar, or you're not clear on the distinction between "fulfill" and "resolve", I go into promise terminology in this post on my blog.)
See comments:
function testCase(urls) {
// Return a promise that will be settled when the various `$.get` calls are
// done.
return Promise.all(urls.map(function(url) {
// Return a promise for this `$.get`.
return $.get(url)
.then(function(response) {
if (response.meta && response.meta.next) {
// This `$.get` has a "next", so return a promise waiting
// for the "next" which we ultimately fulfill (via `return`)
// with an array with both the original response and the
// "next". Note that by returning a thenable, we resolve the
// promise created by `then` to the thenable we return.
return $.get(url + "&offset=" + response.meta.next)
.then(function(nextResponse) {
return [response, nextResponse];
});
} else {
// This `$.get` didn't have a "next", so resolve this promise
// directly (via `return`) with an array (to be consistent
// with the above) with just the one response in it. Since
// what we're returning isn't thenable, the promise `then`
// returns is resolved with it.
return [response];
}
});
})).then(function(responses) {
// `responses` is now an array of arrays, where some of those will be one
// entry long, and others will be two (original response and next).
// Flatten it, and return it, which will settle he overall promise with
// the flattened array.
var flat = [];
responses.forEach(function(responseArray) {
// Push all promises from `responseArray` into `flat`.
flat.push.apply(flat, responseArray);
});
return flat;
});
}
Note how we never use catch there; we defer error handling to the caller.
Usage:
testCase(["url1", "url2", "etc."])
.then(function(responses) {
// Use `responses` here
})
.catch(function(error) {
// Handle error here
});
The testCase function looks really long, but that's just because of the comments. Here it is without them:
function testCase(urls) {
return Promise.all(urls.map(function(url) {
return $.get(url)
.then(function(response) {
if (response.meta && response.meta.next) {
return $.get(url + "&offset=" + response.meta.next)
.then(function(nextResponse) {
return [response, nextResponse];
});
} else {
return [response];
}
});
})).then(function(responses) {
var flat = [];
responses.forEach(function(responseArray) {
flat.push.apply(flat, responseArray);
});
return flat;
});
}
...and it'd be even more concise if we were using ES2015's arrow functions. :-)
In a comment you've asked:
Could this handle if there was a next next? Like a page 3 of results?
We can do that by encapsulating that logic into a function we use instead of $.get, which we can use recursively:
function getToEnd(url, target, offset) {
// If we don't have a target array to fill in yet, create it
if (!target) {
target = [];
}
return $.get(url + (offset ? "&offset=" + offset : ""))
.then(function(response) {
target.push(response);
if (response.meta && response.meta.next) {
// Keep going, recursively
return getToEnd(url, target, response.meta.next);
} else {
// Done, return the target
return target;
}
});
}
Then our main testCase is simpler:
function testCase(urls) {
return Promise.all(urls.map(function(url) {
return getToEnd(url);
})).then(function(responses) {
var flat = [];
responses.forEach(function(responseArray) {
flat.push.apply(flat, responseArray);
});
return flat;
});
}
Assuming you are using jQuery v3+ you can use the promises returned by $.ajax to pass to Promise.all().
What you are missing is returning the second request as a promise instead of trying to push it to the promises array
Simplified example
var promises = urls.map(function(url) {
// return promise returned by `$.ajax`
return $.get(url).then(function(response) {
if (response.meta) {
// return a new promise
return $.get('special-data.json').then(function(innerResponse) {
// return innerResponse to resolve promise chain
return innerResponse;
});
} else {
// or resolve with first response
return response;
}
});
})
Promise.all(promises).then(function(data) {
console.dir(data)
}).catch(function(e) {
console.log(e);
});
DEMO
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 6 years ago.
How can I return the value of reverseGeocodeData using a promise (using the resolve method in the promise)?
geocoder.reverseGeocode(33.7489, -84.3789,function (err, reverseGeocodeData){
//something;
},
// Reverse Geocoding
return new Promise(function(resolve,reject){
resolve();
});
You have to resolve or reject the promise in the callback of the goecoder...
return new Promise(function(resolve, reject) {
geocoder.reverseGeocode(33.7489, -84.3789, function (err, reverseGeocodeData) {
if(err) return reject(err);
resolve(reverseGeocodeData);
});
});
This would be the basic implementation of a Promise. Depending on the promise library you're using there are of course other options. I prefer bluebird or when
this is an example using bluebird.js (http://bluebirdjs.com/docs/api/promise.promisify.html)
var Promise = require('bluebird');
var reverseGeocodePromise = Promise.promisify(geocoder.reverseGeocode);
reverseGeocodePromise(33.7489, -84.3789)
.then(function(result) {
// do something;
})
.catch(function(err) {
// handle error
})