How to create my own promise? - javascript

I have two questions about promises in AngularJS:
How do I create my own promise?
See the code below:
function controller($http) {
var dataCache;
function getData(){
if( dataCache != null ){
// should return my own promise here
// to pass the value of 'dataCache' to 'then' immediately
} else {
return $http.get('...some url ...');
}
}
}
How do I return the last promise?
Code:
function controller($http) {
var urlArr = ['url1', 'url2', 'url3'];
function getDataOneByOne() {
// should call $http.get() for the url in the 'urlArr' one after another in a chain
// and return the last promise
}
}

For the second question, do Array.prototype.reduce on urlArr and build promise chain:
function controller($http, $q) {
var urlArr = ['url1', 'url2', 'url3'];
function getDataOneByOne() {
return urlArr.reduce(function (chain, url) {
return chain.then(function () {
return $http.get(url);
});
}, $q.when());
}
}
Don't forget to handle $http errors, though.

For the first question, I believe you're looking for $q.when(). It wraps a normal value in a promise and resolves it.
function getData(){
if( dataCache !== null ) {
$q.when(dataCache);
} else {
return $http.get('...some url ...');
}
}
getData.then(function() {
});
See Klaster's answer for your second question.

Related

Return Statement not Waiting on Promise

I have a service. Lets say that this returns the string "B".
I have the following controller:
$scope.output;
var someVariable = 'A';
$scope.setUpConnection = function (someVariable) {
$scope.output = createConnection(someVariable);
console.log($scope.output);
}
createConnection = function (someVariable) {
var result;
service.connect(someVariable).then(function success(response) {
result = response.data;
}, function error(response) {
result = 'Error' + response;
});
return result;
}
The createConnection() function jumps to the end of the function, not waiting for the .then, returning nothing and as such returning undefined. Can someone explain why it isn't waiting for the promise to finish?
The service isn't the problem, if I replace the return with a direct
$scope.output = response.data;
it works fine. The problem and the reason it's set up like this is that the createConnection() function will eventually take place in a seperate JS file once I get around to moving it, so the solution above won't work. As such I figured I'd need the return statement.
This will not work because at the time you return the result promise is not resolved. you have to unwrap the promise inside the setUpConnection
$scope.setUpConnection = function (someVariable) {
service.connect(someVariable).then(function success(response) {
$scope.output = response.data;
}, function error(response) {
$scope.output = 'Error' + response;
});
}

javascript: Retrying until promise is resolved and then execute

I am checking whether some elements of my DOM are fully charged and I wanted to do it through a promise function that checks some elements and if not loaded waits for them.
This is my code
var jq = jQuery.noConflict();
var df = jq.Deferred();
function keepTrying() {
try{
var el1 = \\element to search for
var success=true
catch(e){
var success= false
}
if (success) {
//Resolves promises
df.resolve();
return df.promise();
} else {
//Here it retries..
setTimeout(function() {
keepTrying();
}, 500);
}
}
keepTrying();
df.done(function() {
//what to do after
});
Do you think there is an easier way to do it? I am working on Qualtrics so importing external libraries could be tricky when passing from one function to another.
I'd use an inner recursive function, and resolve the promise when the element is found.
You could add a count to that, and reject the promise after n tries etc.
function keepTrying() {
var def = $.Deferred();
(function rec() {
var el = document.getElementById('something');
if ( el === null ) {
setTimeout(rec, 500);
} else {
def.resolve();
}
})();
}
keepTrying().done(function() { ... });

Run same async function multiple times with promises

I have an async function like:
$scope.get_device_version = function(){
return $q(function(resolve, reject){
$http.get('/api/get_version')
.then(function(response) {
resolve(response.data.version);
},function(response) {
reject("Lost connection..");
});
});
};
Question 1: Now I want to run that function 10 times in a row sequentially, what do I do?
Question 2: Now I want to run the function until I get a desired answer from the http-request, what do I do?
Question 1
.then(callback) returns a new promise resolving to the return value of callback, or if the return value is another promise, to the settled value of that promise. This can be used to chain asynchronous calls. For example, given
function myFunction() { return promise; }
the following snippet will call myFunction 10 times sequentially
var result = $q.resolve();
for (var i = 0; i < 10; ++i) {
result = result.then(myFunction);
}
result.then(function () { /* myFunction has been called 10 times */ })
Question 2
Here, recursion is required since you don't know the exact number of times you will need to iterate. For example, given myFunction as above,
function wrapper() {
var deferred = $q.defer();
iter();
function iter(res) {
// skip first iter() call, wait for acceptable res
if (result !== void 0 && /* res is what I want */) {
return deferred.resolve(res);
}
// recurse
return myFunction().then(iter);
}
return deferred.promise;
}
wrapper().then(function (res) { /* res is an acceptable response */ })
Note that for this use case, promises do not really offer an advantage over simple callbacks.
Question 1:
var request = null;
for( var i = 0; i < 10; i++ ) {
if( request )
request.then( $scope.get_device_version );
else
request = $scope.get_device_version();
}
Question 2:
$scope.get_device_version = function(){
return $q(function(resolve, reject){
$http.get('/api/get_version')
.then(function(response) {
if( /*Not a desired answer? run again:*/ )
$scope.get_device_version()
else
resolve(response.data.version);
},function(response) {
reject("Lost connection..");
});
});
};
This is pseudo code, i have not tested it.
var checkDeviceVersion=function (times) {
$scope.get_device_version().then(function(data) {
if(times==0) return;
checkDeviceVersion(times-1);
});
}
var keepChecking=function () {
$scope.get_device_version().then(function(data) {
if(data.condition) return;
keepChecking();
});
}
Invoke then as checkDeviceVersion(10) or keepChecking()

What is the best way to implement promise in the given scenario?

I'm using D.js as promise library for our javascript application.
Following is my sample code:
function getData(deferred) {
var data_one;
// getInfo is returning a promise for async task
getInfo()
.then(function (resp_one) {
data_one = resp_one;
// getInfo2 is also returning another promise
return getInfo2();
})
.then(function (resp_two) {
deferred.resolve('prefix' + data_one + resp_two);
});
};
function sample () {
var d = D(),
data = localStorage.getItem('key');
if (data) {
d.resolve(data);
} else {
getData(d);
}
return d.promise;
}
sample().then(function (data) {
//do something with data.
});
I im invoking sample function. Is the implementation inside the sample function and sub functions following the coding standard for promises?
Im new to promises, Is it good to passing around deferred object to other function to resolve/reject ??
Is there any better way to implement the above functionality??
Thanks in advance..
Looks like you can improve the code if you use promises in more natural way.
First of all if getData returns a Promise then you don't have to pass deferred around, this is considered anti-pattern. You just simply return getInfo().
Another thing, in the sample function if your data might be already available it's convenient to use D.promisify method to return resolved promise with non-promise value:
function getData() {
var data_one;
return getInfo().then(function (resp_one) {
data_one = resp_one;
return getInfo2();
})
.then(function (resp_two) {
return 'prefix' + data_one + resp_two;
});
};
function sample() {
var data = localStorage.getItem('key');
return data ? D.promisify(data) : getData();
}
sample().then(function (data) {
//do something with data.
});

To whom return is returning the value (javascript)?

I saw following code in the HotTowel project. In the following code, callback method for then returns value return vm.messabeCount = data;
(function () {
'use strict';
function dashboard(common, datacontext) {
vm.messageCount = 0;
function getMessageCount() {
return datacontext.getMessageCount().then(function (data) {
/******* Here ********/
return vm.messageCount = data;
});
}
}
})();
Am wondering why & to whom it's returning value. Is it some standard practice? Can't the code be just.
return datacontext.getMessageCount().then(function (data) {
vm.messageCount = data;
});
Or
return datacontext.getMessageCount().then(function (data) {
vm.messageCount = data;
return;
});
getMessageCount is a function returning a promise object. then method of this promise returns another promise again. It makes possible to chain multiple then parts. Each then(function() { ... }) has an ability to modify a data to be passed to the next then invocation. So this construction:
return datacontext.getMessageCount().then(function(data) {
return vm.messageCount = data;
});
means to modify a data passed to resolve callbacks. Without this return success functions would be resolved with undefined value, while we need it to be resolved with data.

Categories

Resources