一幅漫画解释AngularJS中的Promise

5 年前

早上,老爸说:“儿子,天气如何?”

每周一早上,老爸问儿子下午的天气情况,儿子可以到自家房子旁边小山上使用望远镜来观看。儿子在出发时许诺(Promise)老爸(会通知老爸天气情况)。

此刻,老爸决定,如果天气不错,明天就出去捕鱼,否则就不去。而且如果儿子无法获得天气预报的话,也不去捕鱼。

30分钟左右,儿子回来了,每周的结局都不一样。

结局A:成功获得了(retrieved)天气预报,晴天 :)

儿子成功获取了天气预报,天空晴朗,阳光明媚!承诺(Promise)兑现了(resolved),于是老爸决定开始为周日的捕鱼做准备。

结局B:同样成功获得了天气预报,雨天:(

儿子成功获得了天气预报,只不过是乌云密布,要下雨。承诺(Promise)兑现了(resolved),只是老爸决定呆在家里,因为天气很糟糕。

结局C:没法获得天气预报:-/

出了问题,儿子没法得知天气预报,因为雾很大,就算站在小山上也无法看清。儿子没办法对象他离开时许下的诺言, promise was rejected!老爸决定留下来,这并不值得冒险。

从编程的角度来看

在这种情况下,老爸是逻辑控制,他把儿子当做service来处理。

这里面的逻辑我们已经知道了,老爸要儿子给他预报天气,但是儿子没法马上告诉他,于是许诺他会带着天气预报回来,老爸在儿子回来之前有其他的事情要做。当老爸从儿子那获得天气预报之后,再决定是打包出发还是呆在家里。这个故事的重点是,儿子去山顶上看天气这件事并没有妨碍(block)老爸干其他的事情。因此对于这种情况,最好的方式就是许诺,随后再兑现或者不兑现。

我们可是使用Angular的then()指定老爸针对每种结果的对策。then()函数接受两个函数作为参数:一个许诺对现时执行,一个在无法对现时执行。

Controller:FatherCtrl

老爸控制情况:

// 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();
  });
};

Service:SonService

儿子就是一个服务,他爬上小山,尝试预报天气。我们可以把儿子通过望远镜查看即将到来的天气,假设成条用一个天气的API,通常是异步的。要么获得答案,要么出现问题(比方说返回500,大雾皑皑的天空)。 “捕鱼天气API”通过一个许诺返回结果,如果兑现的话,结果的格式像 { "forecast": "good" }这样。

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);
        });
    }
  };
});

总之

老爸让儿子预报的天气就是一个比喻,说明了异步的本质。老爸并不想在门口傻等着儿子回来,他还有别的事情要做。而是在门口许个诺言,决定在3种不同的情况(天气好/坏/不知道)下该怎么办,儿子离开时就许下一个诺言,在他回来的时候会兑现或者食言。

儿子需要处理一个异步的API(通过望远镜来查看天空/使用天气API)来获得天气,但这些对他老爸来说都是未知的,是谁不懂科技!?

原文:Promises in AngularJS, Explained as a Cartoon

0
推荐阅读