AngularJS : 如何在这种情况下使用$q promise 特性来等待数据就绪?
AngularJS : How to use the $q promise feature in this situation to wait for data to be ready?
我有一个 Controller,它在 Factory 中启动一个 API 调用。目前我开始通话,然后我在通话后有一个功能来检查 Array
的状态。但是我不确定如何在收集数据时强制它在这里等待,因此需要某种 $q
实现。
如您在下面的屏幕截图中所见,vs.tickers
return 是一个空对象或数组。最后 GetTickersFactory 中的 console.log
触发:
第一个控制器
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);
}
GetTickersFactory 中的 getTickers 函数 |
也许这有帮助:the Gist for the full 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) {
....
}
}
我在 getTickersFactory.js 内部使用的 return 数组函数我相信我不应该使用它,而是弄清楚如何使用承诺:
function returnPortfolioTickers() {
return portfolioTickers.that;
}
请注意,我最初确实尝试过此操作,但结果相同:
vs.tickers = GetTickersFactory.getTickers('portfolio');
vs.tickers
会 return undefined
如果你想使用 ES6 风格的 promise:
function getTickers(type, load, searchedTicker) {
return $q(function (resolve, reject) {
if (doTheGoodThings()) {
resolve('This is ok!');
} else {
reject('This did not work');
}
}
}
然后在你的控制器中:
if (root.tickerType === 'portfolio') {
GetTickersFactory.getTickers('portfolio').then(function (result) {
console.log('Worked: ' + result);
}, function (error) {
console.log('Error: ' + error);
});
}
你的 switch cases 应该 return 一个 promise,这样当 promise 得到解决时,它的调用函数将 .then
调用
工厂代码
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
}
控制器
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);
};
}
您已经有两个 return 承诺的方法(getWatchList 和 getWatchListRefresh),因此您可以 return 这些方法并链接更多 .then
。这里不用$q。
希望这个简化的示例可以帮助您朝着正确的方向前进...
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;
}
然后在你的控制器中:
// the `tickers` param here will be the result
// returned by renderTickers()
GetTickersFactory.getTickers('portfolio').then(function(tickers) {
vs.tickers = tickers;
});
我有一个 Controller,它在 Factory 中启动一个 API 调用。目前我开始通话,然后我在通话后有一个功能来检查 Array
的状态。但是我不确定如何在收集数据时强制它在这里等待,因此需要某种 $q
实现。
如您在下面的屏幕截图中所见,vs.tickers
return 是一个空对象或数组。最后 GetTickersFactory 中的 console.log
触发:
第一个控制器
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);
}
GetTickersFactory 中的 getTickers 函数 | 也许这有帮助:the Gist for the full 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) {
....
}
}
我在 getTickersFactory.js 内部使用的 return 数组函数我相信我不应该使用它,而是弄清楚如何使用承诺:
function returnPortfolioTickers() {
return portfolioTickers.that;
}
请注意,我最初确实尝试过此操作,但结果相同:
vs.tickers = GetTickersFactory.getTickers('portfolio');
vs.tickers
会 return undefined
如果你想使用 ES6 风格的 promise:
function getTickers(type, load, searchedTicker) {
return $q(function (resolve, reject) {
if (doTheGoodThings()) {
resolve('This is ok!');
} else {
reject('This did not work');
}
}
}
然后在你的控制器中:
if (root.tickerType === 'portfolio') {
GetTickersFactory.getTickers('portfolio').then(function (result) {
console.log('Worked: ' + result);
}, function (error) {
console.log('Error: ' + error);
});
}
你的 switch cases 应该 return 一个 promise,这样当 promise 得到解决时,它的调用函数将 .then
调用
工厂代码
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
}
控制器
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);
};
}
您已经有两个 return 承诺的方法(getWatchList 和 getWatchListRefresh),因此您可以 return 这些方法并链接更多 .then
。这里不用$q。
希望这个简化的示例可以帮助您朝着正确的方向前进...
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;
}
然后在你的控制器中:
// the `tickers` param here will be the result
// returned by renderTickers()
GetTickersFactory.getTickers('portfolio').then(function(tickers) {
vs.tickers = tickers;
});