最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - AngularJS $q.all & multiple $q.defer - Stack Overflow

programmeradmin5浏览0评论

Even though I have managed to make my code work, there is something I don't understand. The following piece of code functions correctly:

socket.on('method', function() {
    var payload = {
      countrycode: '',
      device: ''
    };
    var d1 = $q.defer();
    var d2 = $q.defer();
    $q.all([
      geolocation.getLocation().then(function(position) {
        geolocation.getCountryCode(position).then(function(countryCode){
          payload.countrycode = countryCode;
          d1.resolve(countryCode);
        });
        return d1.promise;
      }),
      useragent.getUserAgent().then(function(ua) {
        useragent.getIcon(ua).then(function(device) {
          payload.device =  device;
          d2.resolve(device);
        });
        return d2.promise
      })
    ]).then(function(data){
      console.log(data); //displays ['value1', 'value2']
    })
  });

Is there a better way of achieving this? Before I had only one deferred variable, i.e. varvar deferred = $q.defer(); but that way the .then() function returned an object with double the results.

So the few question I have are:

  1. Do I need multiple $q.defer vars?
  2. Is the above the best way to wait for two async calls to finish and populate the payload object?

Even though I have managed to make my code work, there is something I don't understand. The following piece of code functions correctly:

socket.on('method', function() {
    var payload = {
      countrycode: '',
      device: ''
    };
    var d1 = $q.defer();
    var d2 = $q.defer();
    $q.all([
      geolocation.getLocation().then(function(position) {
        geolocation.getCountryCode(position).then(function(countryCode){
          payload.countrycode = countryCode;
          d1.resolve(countryCode);
        });
        return d1.promise;
      }),
      useragent.getUserAgent().then(function(ua) {
        useragent.getIcon(ua).then(function(device) {
          payload.device =  device;
          d2.resolve(device);
        });
        return d2.promise
      })
    ]).then(function(data){
      console.log(data); //displays ['value1', 'value2']
    })
  });

Is there a better way of achieving this? Before I had only one deferred variable, i.e. varvar deferred = $q.defer(); but that way the .then() function returned an object with double the results.

So the few question I have are:

  1. Do I need multiple $q.defer vars?
  2. Is the above the best way to wait for two async calls to finish and populate the payload object?
Share Improve this question asked Mar 4, 2014 at 11:25 TamasTamas 11.2k15 gold badges51 silver badges79 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 7
socket.on('method', function() {
    var payload = {
      countrycode: '',
      device: ''
    };
    geolocation.getLocation()
    .then(function(position) {
      return geolocation.getCountryCode(position);
    })
    .then(function(countryCode) {
      payload.countrycode = countryCode;
      return useragent.getUserAgent();
    })
    .then(function(ua) {
      return useragent.getIcon(ua);
    })
    .then(function(device) {
      payload.device =  device;
      console.log(data); //displays ['value1', 'value2']
    });
});

read the promise chaining part

You could always separate your code into smaller semantic blocks like so:

getCountryCode = function() {
  var d = $q.defer();
  geolocation.getLocation()
  .then(function(position) {
    return geolocation.getCountryCode(position)
  })
  .then(function(countryCode) {
    d.resolve(countryCode);
  })
  .fail(function(err) {
    d.reject(err);
  })
  return d.promise;
};

getDevice = function() {
  var d = $q.defer();
  useragent.getUserAgent()
  .then(function(ua) {
    return useragent.getIcon(ua)
  })
  .then(function(device) {
    d.resolve(device);
  })
  .fail(function(err) {
    d.reject(err);
  });
  return d.promise;
}

That will shorten your actual parallel call ($q.all) quite a bit:

socket.on('method', function() {
  $q.all([getCountryCode(), getDevice()])
    .spread(function(countryCode, device) {
      var payload = {
        countryCode: countryCode,
        device: device
      };
      // ... do something with that payload ...
    });
});

To synchronize multiple asynchronous functions and avoid Javascript callback hell: http://fdietz.github.io/recipes-with-angular-js/consuming-external-services/deferred-and-promise.html

发布评论

评论列表(0)

  1. 暂无评论