AngularJS: How to use the $ q promise function in this situation to wait for the data to be ready?
I have a Controller that triggers an API call in a Factory . I am currently running a call, after that I have a function after this call to check the status Array
. However, I'm not sure how to make it wait here while data is being collected, so some implementation is needed $q
.
As you can see in the screenshot below, it vs.tickers
returns an empty object or array. Then finally the console.log
GetTickersFactory runs:
1st controller
if (root.tickerType === 'portfolio') {
// Call to factory to start the API GETS:
GetTickersFactory.getTickers('portfolio');
// I then call a function in the Factory to return the array
// Which isn't ready yet of course since it returns undefined...
vs.tickers = GetTickersFactory.returnPortfolioTickers();
console.log('portfolio');
console.log('vs.tickers = ', vs.tickers);
}
getTickers function in GetTickersFactory | Maybe this helps: Gist for the complete Factory .
function getTickers(type, load, searchedTicker) {
load = load || loadString; searchedTicker = searchedTicker || '';
var portfolioTickersArray = [], searchedTickersArray = [];
tickersPane.loadingTickersDone = false;
switch(type) {
case 'searched':
....
break;
case 'portfolio':
if (portfolioCached) {
// The API Call (cached)
ApiFactory.getWatchList().then(function(data) {
portfolioTickersArray = renderTickers(data.data.tickers, undefined, type);
portfolioTickers.that = portfolioTickersArray;
tickersPane.loadingTickersDone = true;
console.log('portfolioTickersArray: ', portfolioTickersArray);
return portfolioTickersArray;
});
} else {
// The API Call (not cached)
ApiFactory.getWatchListRefresh().then(function(data) {
portfolioTickersArray = renderTickers(data.data.tickers, undefined, type);
portfolioTickers.that = portfolioTickersArray;
portfolioCached = true;
tickersPane.loadingTickersDone = true;
console.log('portfolioTickersArray: ', portfolioTickersArray);
return portfolioTickersArray;
});
}
break;
}
function renderTickers(data, searchedTicker, type) {
....
}
}
The returned array function that I am using inside getTickersFactory.js. I suppose I shouldn't be using this, but figure out how to use promises instead:
function returnPortfolioTickers() {
return portfolioTickers.that;
}
Note. I tried this first, but with the same results:
vs.tickers = GetTickersFactory.getTickers('portfolio');
vs.tickers
will return undefined
source to share
Your switch cases must return a promise for the caller to call .then
when the promise has been resolved.
Factory Code
function getTickers(type, load, searchedTicker) {
//other code remains same
tickersPane.loadingTickersDone = false;
switch (type) {
case 'searched':
return ApiFactory.getTickers(null, load).then(function(data) {
//other code remains same
if (tickersPane.tempTickers.length > 0) {
//other code remains same
return returnData(searchedTickersArray);
}
return []; //return default variable to continue promise chain
});
break;
case 'portfolio':
tickersPane.addOption = false;
tickersPane.removeOption = true;
tickersPane.displayTopTags = false;
tickersPane.displayPortfolio = true;
if (portfolioCached) {
return ApiFactory.getWatchList().then(function(data) {
//other code remains same
return returnData(portfolioTickersArray);
});
} else {
return ApiFactory.getWatchListRefresh().then(function(data) {
//other code remains same
return returnData(portfolioTickersArray);
});
}
break;
}
function renderTickers(data, searchedTicker, type) {
//this should be as is
}
function returnData(data) {
tickersPane.loadingTickersDone = true;
return data;
}
//tickersPane.loadingTickersDone = true;
//return data; //removed this line and move to function
}
controller
if (root.tickerType === 'portfolio') {
// Call to factory to start the API GETS:
GetTickersFactory.getTickers('portfolio').then(resp){
vs.tickers = GetTickersFactory.returnPortfolioTickers();
console.log('portfolio');
console.log('vs.tickers = ', vs.tickers);
};
}
source to share
If you want to use ES6 promise:
function getTickers(type, load, searchedTicker) {
return $q(function (resolve, reject) {
if (doTheGoodThings()) {
resolve('This is ok!');
} else {
reject('This did not work');
}
}
}
And then in your controller:
if (root.tickerType === 'portfolio') {
GetTickersFactory.getTickers('portfolio').then(function (result) {
console.log('Worked: ' + result);
}, function (error) {
console.log('Error: ' + error);
});
}
source to share
You already have two methods that return promises (getWatchList and getWatchListRefresh), so you can just return those methods and chain more .then
s. There is no need to use $ q here.
Hope this simplified example helps you in the right direction ...
function getTickers(type) {
var tickers;
switch(type) {
// ...
case 'portfolio':
var getList = portfolioCached ? getWatchList : getWatchListRefresh;
// tickers will be set to the promise returned
// by getWatchList or getWatchListRefresh
tickers = getList().then(function(data) {
if (!portfolioCached) {
portfolioCached = true;
}
// the result returned by renderTickers will be
// passed to any `.then` that is chained
return renderTickers(data.data.tickers, undefined, type);
});
break;
}
// return the tickers promise
return tickers;
}
Then in your controller:
// the `tickers` param here will be the result
// returned by renderTickers()
GetTickersFactory.getTickers('portfolio').then(function(tickers) {
vs.tickers = tickers;
});
source to share