当前位置: 首页 > 知识库问答 >
问题:

谭景福
2023-03-14

我有一个服务,它公开了一个函数,该函数接收一个解析的CSV(使用Papapass),并promise反映解析状态:
如果文件缺少强制字段,promise将被拒绝
否则,它将每行解析为一个项,并自动填充缺少字段(自动填充过程是异步的)。
所有项都被填充时,函数用项数组解析promise

我要测试函数是onCsvParse:

angular.module('csvParser', [])
  .factory('csvParser', ['$http',
    function($http) {
      var service = {
        onCsvParse: function(results, creatingBulkItems) {
          var errors = this.getCsvErrors(results);
          if (errors.length > 0) {
            //reject
            creatingBulkItems.reject(errors);
          } else {

            var items = this.parseCsv(results);
            var autoPopulateItems = [],
              populatedItems = [];
            for (var i = 0; i < populatedItems.length; i++) {
              var item = items[i];
              if (item.name === "" /*or some any field is missing */ ) {
                // auto populate item
                autoPopulateItems.push(this.autoPopulateItem(item));
              } else {
                var populatedItem = $q.when(item);
                populatedItems.push(populatedItem);
              }
            }
            populatedItems =autoPopulateItems.concat(populatedItems);
            var populatingAllItems = $q.all(populatedItems);
            populatingAllItems.then(function(items) {
              creatingBulkItems.resolve(items);
            }, function(err) {
              creatingBulkItems.resolve(err);
            });
          }
        },
        autoPopulateItem: function(newItem) {
          var populatingItem = $q.defer();
          var item = angular.copy(newItem);
          $http.post('api/getItemData', { /*.....*/ })
            .success(function(response) {
              //----Populate item fields
              item.name = response.name;
              //....
              //resolve the promise
              populatingItem.resolve(item)

            }).error(err) {
              // resolving on error for $q.all indication
              populatingItem.resolve(item)
            };
          return populatingItem.promise;

        }
      }
      return service;
    }
  ])

我对该方法的测试如下(简化):

describe('bulk items upload test', function() {
  //upload csv & test scenarios...
  var $rootScope, $q, csvResults = {};
  var $httpBackend, requestHandler;
  beforeEach(module('csvParser'));

  beforeEach(inject(function(_$rootScope_, _$q_) {
    $rootScope = _$rootScope_;
    $q = _$q_;
  }));
  beforeEach(inject(function($injector) {
    // Set up the mock http service responses
    $httpBackend = $injector.get('$httpBackend');
    // backend definition common for all tests
    requestHandler = $httpBackend.when('POST', 'api/getItemData')
      .respond({
        name: "name",
        description: "description",
        imageUrl: "www.google.com"

      });


    //   afterEach(function(){ $rootScope.$apply();});

  }));
  it('Should parse csv string', function(done) {
    var csvString = "Name,Description of the page";//...

    Papa.parse(csvString, {
      complete: function(results) {
        csvResults = results;
        done();
      }
    });

  });
  it('Should fail', function(done) {
    var creatingBulkItems = $q.defer();
    console.log("here..");
    csvParser.onCsvParse(csvResults, creatingBulkItems);
    creatingBulkItems.promise.then(function() {
      console.log("1here..");
      //promise is never resolved
      expect(1).toEqual(1);
      done();
    }, function() {
      //promise is never rejeceted
      console.log("2here..");
      expect(1).toEqual(1);
      done();
    });
    $rootScope.$apply();

  });

});

这样我得到了一个错误:error:Timeout-Async回调没有在jasmine指定的超时内调用。默认超时时间间隔。

虽然我调用了$rootScope,但promise没有得到解决$apply()并且我也没有调用真正的异步调用(只调用mock,除了$q.all)。我怎样才能让它工作?

共有2个答案

韦德厚
2023-03-14

读完这篇文章后:https://gist.github.com/domenic/3889970 我发现了我的问题
关键的一点是使用promise扁平化promise链。然后返回值。

这个[promise.then]函数应该返回一个新的promise,当给定的满足处理程序或错误处理程序回调结束时,这个promise就会实现。这允许将promise操作链接在一起。从回调处理程序返回的值是返回的promise的实现值。如果回调抛出一个错误,返回的promise将被移动到失败状态。

不是在内部promise成功/失败回调中解决外部promise,而是在内部promise.then回调中解决外部promise

所以我的解决方案是这样的:

onCsvParse: function(results) {
      var errors = this.getCsvErrors(results);
      if (errors.length > 0) {
         var deferred = $q.defer();
        //reject
        return deferred.reject(errors);
      } else {

        var items = this.parseCsv(results);
        var autoPopulateItems = [],
          populatedItems = [];
        for (var i = 0; i < populatedItems.length; i++) {
          var item = items[i];
          if (item.name === "" /*or some any field is missing */ ) {
            // auto populate item
            autoPopulateItems.push(this.autoPopulateItem(item));
          } else {
            var populatedItem = $q.when(item);
            populatedItems.push(populatedItem);
          }
        }
        populatedItems = autoPopulateItems.concat(populatedItems);
        var populatingAllItems = $q.all(populatedItems);
        return populatingAllItems.then(function(items) {
            return items;
        }, function(err) {
          return err;
        });
      }
    },

测试代码:

it('Should not fail :)', function(done) {
csvParser.onCsvParse(csvResults).then(function(items) {
  //promise is resolved
  expect(items).not.toBeNull();
  done();
}, function() {
  //promise is rejeceted
  //expect(1).toEqual(1);
  done();
});
$rootScope.$apply();});
诸葛卜霸
2023-03-14

无效的语法。您需要传递一个函数错误回调。

        }).error(function(err) {
          // resolving on error for $q.all indication
          populatingItem.resolve(item)
        });
      return populatingItem.promise;

另外你jasime测试需要一些更多的初始化:http://plnkr.co/edit/wjykvpwtRA0kBBh3LcX3?p=preview

 类似资料:
  • 本文向大家介绍列举一个你觉得互联网中存在价格歧视的产品,并从开发者与用户的角度来分析这种歧视是否合理。相关面试题,主要包含被问及列举一个你觉得互联网中存在价格歧视的产品,并从开发者与用户的角度来分析这种歧视是否合理。时的应答技巧和注意事项,需要的朋友参考一下 举例:携程会就同一产品对不同画像的用户提供不同面额的优惠券,从而导致不同用户购买同一产品所支付的实际价格有差异。 开发者角度:合理。不同画像

  • 本文向大家介绍请你从产品角度分析一下拼多多。相关面试题,主要包含被问及请你从产品角度分析一下拼多多。时的应答技巧和注意事项,需要的朋友参考一下 产品优势:     下沉市场用户基数可观,从用户日常高频消费场景入手     主流用户群体的特征,与微信娱乐流量的契合,流量转化率较高,通过每日签到、小游戏等方式每日唤醒用户,提高产品活跃度     以分享砍价、拼团等社交化电商玩法,充分利用了用户的碎片化

  • 本文向大家介绍你如何看待子弹短信?从产品的角度,简要对比分析微信和子弹短信。相关面试题,主要包含被问及你如何看待子弹短信?从产品的角度,简要对比分析微信和子弹短信。时的应答技巧和注意事项,需要的朋友参考一下 1. 产品定位: 子弹短信 定位只是一个通讯工具。 微信 已经从通讯工具泛化为一个包含支付、小程序、公众号生态的平台级应用。 2. 目标用户: 子弹短信 想解决那些日处理消息量非常大的人群的需

  • 问题内容: 我正在创建路径,并使用和在每个路径中添加多行。然后绘制所有路径。但是某些路径中的线之间有1-2个像素的间隔。如何删除这些空格?我的代码是这样的: 问题答案: 也许这会创造你想要的 :)

  • 问题内容: 嗨,我正在尝试创建仿射变换,使我可以将一个三角形变换为另一个三角形。我所拥有的是2个三角形的坐标。你能帮助我吗? 按照亚当·罗森菲尔德的回答,我想出了这段代码,以防万一有人无聊地自己解决方程: 问题答案: 我假设您在这里谈论2D。仿射变换矩阵中有9个值: 有3个顶点输入,和,当其转化应该成为,,。然而,由于我们在齐次坐标的工作,应用到不一定给-它给人的倍数。所以,我们也有未知的乘法器,

  • 本文向大家介绍从2015年起,微博首页信息流的内容从严格时间排序改为智能排序,请你列举一下影响微博智能排序的因素有哪些?并从多角度分析从时间排序变为智能排序给微博带来哪些收益。相关面试题,主要包含被问及从2015年起,微博首页信息流的内容从严格时间排序改为智能排序,请你列举一下影响微博智能排序的因素有哪些?并从多角度分析从时间排序变为智能排序给微博带来哪些收益。时的应答技巧和注意事项,需要的朋友参

  • 本文向大家介绍列举 3 种目前比较热的手机 APP,说明对应类别后并对其进行简要描述(提示:可从目标人群、主要功能特点、使用场合等多种角度进行描述)。最后请分析这些 app 如何能够成为热门 app。相关面试题,主要包含被问及列举 3 种目前比较热的手机 APP,说明对应类别后并对其进行简要描述(提示:可从目标人群、主要功能特点、使用场合等多种角度进行描述)。最后请分析这些 app 如何能够成为热

  • 本文向大家介绍1、注册帐号是使用互联网的重要环节,列出常见的4种帐号注册方式2、从用户角度分析比较各注册方式优缺点,3、从产品角度分析为何部分产品仅允许使用手机号注册。相关面试题,主要包含被问及1、注册帐号是使用互联网的重要环节,列出常见的4种帐号注册方式2、从用户角度分析比较各注册方式优缺点,3、从产品角度分析为何部分产品仅允许使用手机号注册。时的应答技巧和注意事项,需要的朋友参考一下 1、手机