AngularJS : How to use the $q promise feature in t

2019-05-15 15:54发布

I have a Controller which starts an API call in a Factory. Currently I start the call, then I have a function after that call to check the status of the Array. However I'm not sure how to force it to wait here while the data is being gathered, thus the need for some kind of $q implementation.

As you can see in the screenshot below, vs.tickers returns an empty Object, or Array. Then finally the console.log in GetTickersFactory fires:

enter image description here

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 the GetTickersFactory | Perhaps this helps: 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) {
        ....
    }
}

The return Array function I'm using inside of the getTickersFactory.js I believe I shouldn't use this however and figure out how to use promises instead:

function returnPortfolioTickers() {
    return portfolioTickers.that;
}

Note I did originally try this, but with the same results:

vs.tickers = GetTickersFactory.getTickers('portfolio');

vs.tickers would return undefined

3条回答
一夜七次
2楼-- · 2019-05-15 16:37

If you want to use the ES6-styled 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);
  });

}
查看更多
混吃等死
3楼-- · 2019-05-15 16:44

You already have two methods that return promises (getWatchList and getWatchListRefresh) so you can just return those methods and chain more .thens. No need to use $q here.

Hopefully this simplified example might help steer 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;
});
查看更多
姐就是有狂的资本
4楼-- · 2019-05-15 16:55

Your switch cases should return a promise so that it caller function will .then called when promise gets 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);
    };
}
查看更多
登录 后发表回答