在多个控制器中看到的promise分辨率



我希望在一个服务中解决一些承诺后,两个不同的控制器运行不同的功能(我不希望这个服务每次控制器需要数据时都发出http请求,我只想要一个http请求)。

我有一个服务可以提出请求并得到承诺。我希望controller1看到这个解决方案,然后运行一些代码。然后,我希望controller2也能看到这个promise解析并运行一些代码(基本上是在同一个promise上运行但来自不同文件的多个then()方法)。我该怎么做?

我看到的所有例子都有一个控制器在某个promise解析后运行代码,但没有多个控制器在侦听同一个promise来解析。

以下是我从本文中借用的一些代码(我将添加一个"母亲控制器"来说明我的示例,我不希望儿子服务进行两次http调用):http://andyshora.com/promises-angularjs-explained-as-cartoon.html

子服务

app.factory('SonService', function ($http, $q) {
    return {
        getWeather: function() {
            // the $http API is based on the deferred/promise APIs exposed by the $q service
            // so it returns a promise for us by default
            return $http.get('http://fishing-weather-api.com/sunday/afternoon')
                .then(function(response) {
                    if (typeof response.data === 'object') {
                        return response.data;
                    } else {
                        // invalid response
                        return $q.reject(response.data);
                    }
                }, function(response) {
                    // something went wrong
                    return $q.reject(response.data);
                });
        }
    };
});

父控制器:

 // function somewhere in father-controller.js
        var makePromiseWithSon = function() {
            // This service's function returns a promise, but we'll deal with that shortly
            SonService.getWeather()
                // then() called when son gets back
                .then(function(data) {
                    // promise fulfilled
                    if (data.forecast==='good') {
                        prepareFishingTrip();
                    } else {
                        prepareSundayRoastDinner();
                    }
                }, function(error) {
                    // promise rejected, could log the error with: console.log('error', error);
                    prepareSundayRoastDinner();
                });
        };

母控制器:

var makePromiseWithSon = function() {
            SonService.getWeather()
                // then() called when son gets back
                .then(function(data) {
                    // promise fulfilled
                    if (data.forecast==='good') {
                        workInTheGarden();
                    } else {
                        sweepTheHouse();
                    }
                }, function(error) {
                    // promise rejected, could log the error with: console.log('error', error);
                    sweepTheHouse();
                });
        };

要让您的工厂服务只获取一次url,请将httpPromise存储在您的工厂服务器中。

app.factory('SonService', function ($http) {
    var weatherPromise;
    function getWeather() {
      return $http.get('http://fishing-weather-api.com/sunday/afternoon')
                .then(function(response) {
                    if (typeof response.data === 'object') {
                        return response.data;
                    } else {
                        // invalid response
                        throw response;
                    }
                }, function(response) {
                    // something went wrong
                    throw response;
                });
    }
    function sonService() {
      if (!weatherPromise) {
        //save the httpPromise
        weatherPromise = getWeather();
      }
      return weatherPromise;
    }
    return sonService;
});

简单的答案是,以一种非角度特定的方式(但很容易应用于angular),创建一个缓存ON-OUTBOUND-REQUEST的服务(而不是像大多数系统那样缓存返回值)。

function SearchService (fetch) {
  var cache = { };
  return {
    getSpecificThing: function (uri) {
      var cachedSearch = cache[uri];
      if (!cachedSearch) {
        cachedSearch = fetch(uri).then(prepareData);
        cache[uri] = cachedSearch;
      }
      return cachedSearch;
    }
  };
}

function A (searchService) {
   var a = this;
   Object.assign(a, {
     load: function ( ) {
       searchService.getSpecificThing("/abc").then(a.init.bind(a));
     },
     init: function (data) { /* ... */ }
   });
}
function B (searchService) {
  var b = this;
  Object.assign(b, {
    load: function ( ) {
      searchService.getSpecificThing("/abc").then(b.init.bind(b));
    },
    init: function (data) { /* ... */ }
  });
}

var searchService = SearchService(fetch);
var a = new A(searchService);
var b = new B(searchService);
a.load().then(/* is initialized */);
b.load().then(/* is initialized */);

他们共享相同的承诺,因为与他们交谈的服务缓存并返回了相同的承诺。

如果您希望安全,可以缓存一个promise,然后返回基于缓存的promise解析(或拒绝)的promise的新实例。

// instead of
return cachedSearch;
// replace it with
return Promise.resolve(cachedSearch);

现在,每次发出请求时,每个用户都会获得一个新实例,但每个实例也会根据原始缓存调用通过或失败
当然,你可以更进一步,对缓存设置时间限制,或者使用钩子使缓存无效,或者其他什么。。。

将其转换为Angular也是一个快速

  • SearchService是一项服务
  • AB是控制器
  • 使用$http而不是fetch(尽管fetch非常漂亮)
  • fetch( ).then(prepareData)中,您将在成功时从JSON转换数据
    $http中,您将返回response.data,因为您的用户不希望这样做
    无论哪种方式,每次出站调用都只执行一次该操作,所以也要缓存它
  • 使用$q(和q方法)而不是本机Promise
  • 使用angular.extend,而不是Object.assign
  • 你完了;您现在已经将整个概念移植到Angular AND VanillaJS中

相关内容

  • 没有找到相关文章

最新更新