This question already has answers here:
setting a variable to get return from call back function using promise
(2 answers)
Closed 8 years ago.
I'm new to Promise's and I'm trying to wrap my head around getting the value.
Here's an idea of what I'm trying to do:
API = {
get: function() {
return new Promise(function(res) {
setTimeout(function() {
res('foo')
}, 1000)
})
}
}
var foo = API.get()
console.log(foo)
It's important that var foo = API.get() remains as it is.
Any idea what to do here?
Promises are still asynchronous. You still can't inspect their value in synchronous code.
You need:
API.get().then(function(result) {
// Resolved value from the Promise object returned by API.get()
console.log(result);
});
API.get() returns a promise object, you then invoke the .then() method on that object.
Another more verbose way would be:
var fooPromise = API.get();
fooPromise.then(function(result) {
console.log(result);
});
Promises are about something happening in the future; you cannot examine their eventual values now unless you are in possession of a time machine.
I am not suggesting you do this, but merely for didactic purposes, if you really want your code to function as you seem to, you could redefine console.log to be promise-aware:
console.log = function() {
var old_console_dot_log = console.log.bind(console);
return function(maybe_promise) {
Promise.resolve(maybe_promise).then(old_console_dot_log);
};
}();
(This version only handles one argument; handling more is left as an exercise.)
Now when you say console.log(foo), it will log the resolved value of foo, but only when it is good and ready, one second from now.
Related
This question already has answers here:
Is it bad practice to have a constructor function return a Promise?
(5 answers)
Closed 6 years ago.
I am new to javascript, I need some help understanding how promises(using bluebird) should be used. Below is my code and I want the constructor to initialize a property after property is resolved.
var getCookie = function(object, someParams) {
return connect(someParams)
.then(function(response){
self.cookie = response.cookie;//this should be done as part of object initialization.
done();
});
}
var app = function(){
var self = this;
getCookie(self);
//how to make sure that return happens after promise is resolved?
return self;
}
how to make sure that return happens after promise is resolved?
You can't. The app function will return before the promise is resolved. That is even guaranteed by JavaScript.
How to call promise object in constructor to set a property
You don't.
Instead you have something like a factory method that creates a new instance of the class, and returns a promise that resolves to the instance.
Example:
function getCookie(someParams) {
return connect(someParams)
.then(function(response){
return response.cookie;
});
}
function App() {}
function getApp() {
var app = new App();
return getCookie(params)
.then(function (cookie) {
app.cookie = cookie;
return app;
});
}
// Usage
getApp().then(function(app) {
// use app
});
One uses promises for asynchronous processes. Constructor functions are synchronous. While you can use promises in constructors, the returned instance won't be fully initialized until the promise is resolved. But your code would never know when that is.
That's why having a factory method that returns a promise that resolves to the class instance if the more reliable way.
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 3 years ago.
The community reviewed whether to reopen this question 11 months ago and left it closed:
Original close reason(s) were not resolved
I need to get the response.data out of the promise so it can be returned by the enclosing function. I know, I probably can't do it the way I've coded it because of normal JavaScript scope. Is there any way, it can be done?
The console.log at #1 produces the correct data. console.log #2 always produces 'a';
function addSiteParentId(nodeId) {
var theParentId = 'a';
var parentId = relationsManagerResource.GetParentId(nodeId)
.then(function(response){
theParentId = response.data;
console.log(theParentId); // #1
});
console.log(theParentId); // #2
return theParentId;
}
Any pointers would be appreciated.
One of the fundamental principles behind a promise is that it's handled asynchronously. This means that you cannot create a promise and then immediately use its result synchronously in your code (e.g. it's not possible to return the result of a promise from within the function that initiated the promise).
What you likely want to do instead is to return the entire promise itself. Then whatever function needs its result can call .then() on the promise, and the result will be there when the promise has been resolved.
Here is a resource from HTML5Rocks that goes over the lifecycle of a promise, and how its output is resolved asynchronously:
https://web.dev/promises/
I also don't like using a function to handle a property which has been resolved again and again in every controller and service. Seem I'm not alone :D
Don't tried to get result with a promise as a variable, of course no way. But I found and use a solution below to access to the result as a property.
Firstly, write result to a property of your service:
app.factory('your_factory',function(){
var theParentIdResult = null;
var factoryReturn = {
theParentId: theParentIdResult,
addSiteParentId : addSiteParentId
};
return factoryReturn;
function addSiteParentId(nodeId) {
var theParentId = 'a';
var parentId = relationsManagerResource.GetParentId(nodeId)
.then(function(response){
factoryReturn.theParentIdResult = response.data;
console.log(theParentId); // #1
});
}
})
Now, we just need to ensure that method addSiteParentId always be resolved before we accessed to property theParentId. We can achieve this by using some ways.
Use resolve in router method:
resolve: {
parentId: function (your_factory) {
your_factory.addSiteParentId();
}
}
then in controller and other services used in your router, just call your_factory.theParentId to get your property.
Referce here for more information:
http://odetocode.com/blogs/scott/archive/2014/05/20/using-resolve-in-angularjs-routes.aspx
Use run method of app to resolve your service.
app.run(function (your_factory) { your_factory.addSiteParentId(); })
Inject it in the first controller or services of the controller. In the controller we can call all required init services. Then all remain controllers as children of main controller can be accessed to this property normally as you want.
Chose your ways depend on your context depend on scope of your variable and reading frequency of your variable.
You have to return a promise instead of a variable.
So in your function just return:
return relationsManagerResource.GetParentId(nodeId)
And later resolve the returned promise.
Or you can make another deferred and resolve theParentId with it.
This question already has an answer here:
Is there a way to tell if an ES6 promise is fulfilled/rejected/resolved? [duplicate]
(1 answer)
Closed 6 years ago.
Suppose some code does
// promise.js
let p = new Promise(() => { /* ... */ })
export default p
where Promise is an ES6 Promise. Suppose some other code has a reference only to p. How can that code tell if p is resolved or not?
// other.js
import p from './promise.js'
// console.log('p is resolved?', ______)
Is there something we can fill in the blank with that would show true or false depending on whether the promise is resolved or not?
Quoting the MDN documentation:
By design, the instant state and value of a promise cannot be inspected synchronously from code, without calling the then() method.
So, you need to call the .then method.
The ES6 Promise constructor does not have a property that can tell you the state of the promise. You need to do something like this:
import p from './promise.js'
var isResolved = false;
p.then(function() {
isResolved = true;
});
// ... At some point in the future.
console.log('p is resolved?', isResolved);
There is an internal property called PromiseState but you can't access it. Here is the spec.
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 4 years ago.
I am relative new to node.js and I ran into a problem where a function is returning undefined. I use console.log to make sure that it returns the proper value and it does. But in the script that makes the call to the function shows as undefined. I think this may be an issue with async programming? I am trying to learn more on how promises work in node.js. What am I doing wrong?
The reason why I believe that it is a problem with async is because console.log is printing to the console undefined before the console.log in getCurrentFrameName();. var name is being assigned undefined.
frameHandler.switchToFrame('top_page');
var name = frameHandler.getCurrentFrameName();
console.log(name);
The console.log in this method prints to the console after the console.log in the code above. The value printed to the console of name is top_page.
this.getCurrentFrameName = function()
{
driver.executeScript('return self.name').then(function(name) {
console.log(name);
return name;
});
};
You can do this:
this.getCurrentFrameName = function(callback) {
driver.executeScript('return self.name').then(function(name) {
return callback(name);
});
};
and then call it like this:
frameHandler.getCurrentFrameName(function(name) {
console.log(name);
});
this will fix your problem, but yes, is a sync problem.
Yes, this is an issue with asynchronous programming. You cannot return a value from an asynchronous callback.
This is because the callback waits for the asynchronous script to execute, and so, node immediately passes control to the next line after the callback.
In your case, console.log(name); gets called before the callback is executed. Hence, the undefined.
The simplest solution to the current situation is to perform the necessary computations within the callback itself.
However, in more complicated situations (such as, callback within callback) you can easily end up with what is known as callback hell.
There are several ways to deal with callback hell: one of them is something called Promise.
What a Promise does essentially, is that it brings a sense of linearity to the code, thus making it easier to understand and maintain.
In your case, you can do this:
this.getCurrentFrameName = function() {
var myPromise = driver.executeScript('return self.name');
myPromise.then(function(name) {
// Do all computation with `name` here
});
};
This question already has answers here:
jQuery deferreds and promises - .then() vs .done()
(11 answers)
Closed 7 years ago.
There is not much answer for this simple question that I have. My main question is that I have seen the .then method used a lot in JavaScript and I know the main thing where randomobject.then(//This returns success, //this returns failure). But there are things that I don't get such as the code here:
var success = function (response) {
return response.data;
};
var error = function (errResponse) {
$log.error(errResponse.data.Message);
};
function getsomeData() {
var url = baseUrl + 'api/somedata';
return $http.get(url).then(success, error);
}
First off in that code I'm wondering how the var success knows what data it is getting and the same with error. It says response.data but what is response? It's probably the result of the http.get but that doesn't make much sense code wise. Also it seems that when I have a function for example.
getsomeData returns what it returns. Why doesn't it work if I do the ff:
var dataHolder = randomAngularService.getsomeData()
it returns an object that holds a data under $$state but somehow the .then makes it work if you do the ff:
randomAngularService.getsomeData().then(function (response) {
if(response != null) {
console.log('got the data');
$scope.meeData = response;
}
});
I thought the .then only takes two parameters? This is what's confusing me.
Also is the .then property a JavaScript method or a jQuery one?
It's used to replace (or provide an alternate way) the old callback mechanism with a cleaner way to handle asynchronous requests, instead of passing your callbacks as parameters, you can chain your function with .then, given function will be executed once the promise gets resolved.
Anyhow, this is just a basic explanation, you should really get into the books of promises for more info.
I'm lazy to explain the whole promise thing, but just to answer question about .then
The 2 arguments inside .then actually means "call this function when the promise is resolved(success)/rejected(failed)"
About the arguments inside the functions, they should be specified in the API, because the caller (for instance $http.get) get to decide what to pass when calling that function.