1

My production code has this chunk of logic, compiled from CoffeeScript:

results = [];
results.push(slowOpA());
results.push(slowOpB());
results.push(slowOpC());
results = _.flatten(results);
$.when.apply($, results).then(onComplete).fail(onError).always(function() {
    $(document).trigger('stop')
});

I would expect this to first call all the slowOp* methods in sequence, then call either onComplete or onError exactly once, and finally call always exactly once. So that's what I test for with Jasmine:

@stopSpy = jasmine.createSpy '<stopSpy>'
$(document).bind 'stop', @stopSpy
...
@lastPromise = new $.Deferred()
spyOn('slowOpA').andReturn new $.Deferred().resolve()
spyOn('slowOpB').andReturn new $.Deferred().resolve()
spyOn('slowOpC').andReturn @lastPromise
...
@lastPromise.resolve()
expect(@stopSpy).toHaveBeenCalledOnce()

And 99 out of 100 times that works, but every now and then it gets 2 or 3 calls instead:

Expected spy on <stopSpy> to have been called once, but was called '2' times

Am I missing something? Or is this some obscure race condition in jQuery/Jasmine?

4

1 に答える 1

1

私は Jasmine に慣れていませんが、あなたの JavaScript コードは正しいです。jsFiddle で同等のものをモックアップしたところ、期待どおりに機能しました。「then(onComplete)」を「done(onComplete)」および「then(onComplete, onError)」と交換しましたが、すべて期待どおりに機能しました。私は、slowOpX が返された deferred/promise を想定していました。アンダースコア (?) _.flatten(results) は冗長ですが、それが問題を引き起こすとは思えません。

于 2012-08-02T22:22:13.603 に答える