欢迎来到承诺(d)地狱;-)

Welcome to promise(d) hell ;-)

本文关键字:地狱 承诺      更新时间:2023-09-26

我想仅使用 promise 异步加载一些文件,并编写了以下解决方案:

function create(ids, $q, http) {
      var promises = [];
      _.each(ids, function(id) {
        var item = http.get('catalog/' + id + '.json').then(function (response) {
          return {id: id, item: response.data};
        }, function(reason) {
          console.log(reason.config.url, reason.statusText, reason.status);
        });
        promises.push(item);
      });
      return $q.all(promises).then(function(values) {
        var catalog = {};
        var svgPromises = [];
        _.each(values, function(value) {
          catalog[value.id] = value.item;
          var svg = http.get('catalog/' + value.item.svg).then(function (response) {
            return {id: value.id, svg: response.data};
          }, function(reason) {
            console.log(reason.config.url, reason.statusText, reason.status);
          });
          svgPromises.push(svg);
        });
        return $q.all(svgPromises).then(function(values) {
          _.each(values, function(value) {
            catalog[value.id].svg = value.svg;
          });
          return catalog;
        });
      });
    }

真的不喜欢它,我知道我可以用地图做得更好一点,但我不相信,我做得对。有谁知道如何做得更好?

function create(ids, $q, http) {
  var catalog = {};
  return $q.all(_.map(ids, function(id) {
    return http.get('catalog/' + id + '.json')
      .then(function(response) {
        catalog[id] = {id: id, item: response.data};
        return http.get('catalog/' + response.data.svg);
      })
      .then(function(response) {
        catalog[id].svg = response.data;
      })
      .catch(function(e) {
        console.log(e.config.url, e.statusText, e.status);
      });
  })).then(function() {
    return catalog;
  });
}

创建第三个延迟对象,然后我们仅在所有调用完成后解析延迟对象怎么样?(下面的代码中可能有一些错误,因为我无法测试它,但希望这个想法很清楚)

function create(ids, $q, http) {
  var promises = [];
  var catalog = {};
  _.each(ids, function (id) {
    var svgDef = $q.defer();
    http.get('catalog/' + id + '.json')
      .then(
      function (response) {
        var value = {id: id, item: response.data};
        catalog[value.id] = value.item;
        http.get('catalog/' + value.item.svg)
          .then(
          function (response) {
            catalog[value.id].svg = response.data;
            svgDef.resolve(catalog[value.id]);
          },
          function (reason) {
            console.log(reason.config.url, reason.statusText, reason.status);
            svgDef.reject(reason);
          });
      },
      function (reason) {
        console.log(reason.config.url, reason.statusText, reason.status);
        svgDef.reject(reason);
      });
    promises.push(svgDef.promise);
  });
  return $q.all(promises)
    .then(function () {
      return catalog;
    })
}