Adding mapbox-gl branch
This commit is contained in:
@@ -0,0 +1,236 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!--
|
||||
Copyright 2012 The Closure Library Authors. All Rights Reserved.
|
||||
|
||||
Use of this source code is governed by the Apache License, Version 2.0.
|
||||
See the COPYING file for details.
|
||||
-->
|
||||
<head>
|
||||
<title>Closure Unit Tests - goog.result.chain</title>
|
||||
<script src="../base.js"></script>
|
||||
<script>
|
||||
|
||||
goog.require('goog.Timer');
|
||||
goog.require('goog.result');
|
||||
goog.require('goog.testing.MockClock');
|
||||
goog.require('goog.testing.jsunit');
|
||||
goog.require('goog.testing.recordFunction');
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
|
||||
var givenResult, dependentResult, counter, actionCallback;
|
||||
var mockClock;
|
||||
|
||||
function setUpPage() {
|
||||
mockClock = new goog.testing.MockClock();
|
||||
mockClock.install();
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
mockClock.reset();
|
||||
givenResult = new goog.result.SimpleResult();
|
||||
dependentResult = new goog.result.SimpleResult();
|
||||
counter = new goog.testing.recordFunction();
|
||||
actionCallback = goog.testing.recordFunction(function(result) {
|
||||
return dependentResult;
|
||||
});
|
||||
}
|
||||
|
||||
function tearDown() {
|
||||
givenResult = dependentResult = counter = null;
|
||||
}
|
||||
|
||||
function tearDownPage() {
|
||||
mockClock.uninstall();
|
||||
}
|
||||
|
||||
// SYNCHRONOUS TESTS:
|
||||
|
||||
function testChainWhenBothResultsSuccess() {
|
||||
var finalResult = goog.result.chain(givenResult, actionCallback);
|
||||
goog.result.wait(finalResult, counter);
|
||||
|
||||
givenResult.setValue(1);
|
||||
dependentResult.setValue(2);
|
||||
|
||||
assertSuccess(actionCallback, givenResult, 1);
|
||||
assertSuccess(counter, finalResult, 2);
|
||||
}
|
||||
|
||||
function testChainWhenFirstResultError() {
|
||||
var finalResult = goog.result.chain(givenResult, actionCallback);
|
||||
goog.result.wait(finalResult, counter);
|
||||
|
||||
givenResult.setError(4);
|
||||
|
||||
assertNoCall(actionCallback);
|
||||
assertError(counter, finalResult, 4);
|
||||
}
|
||||
|
||||
function testChainWhenSecondResultError() {
|
||||
var finalResult = goog.result.chain(givenResult, actionCallback);
|
||||
goog.result.wait(finalResult, counter);
|
||||
|
||||
givenResult.setValue(1);
|
||||
dependentResult.setError(5);
|
||||
|
||||
assertSuccess(actionCallback, givenResult, 1);
|
||||
assertError(counter, finalResult, 5);
|
||||
}
|
||||
|
||||
function testChainCancelFirstResult() {
|
||||
var finalResult = goog.result.chain(givenResult, actionCallback);
|
||||
goog.result.wait(finalResult, counter);
|
||||
|
||||
goog.result.cancelParentResults(finalResult);
|
||||
|
||||
assertNoCall(actionCallback);
|
||||
assertTrue(givenResult.isCanceled());
|
||||
assertTrue(finalResult.isCanceled());
|
||||
}
|
||||
|
||||
function testChainCancelSecondResult() {
|
||||
var finalResult = goog.result.chain(givenResult, actionCallback);
|
||||
goog.result.wait(finalResult, counter);
|
||||
|
||||
givenResult.setValue(1);
|
||||
goog.result.cancelParentResults(finalResult);
|
||||
|
||||
assertSuccess(actionCallback, givenResult, 1);
|
||||
assertTrue(dependentResult.isCanceled());
|
||||
assertTrue(finalResult.isCanceled());
|
||||
}
|
||||
|
||||
function testDoubleChainCancel() {
|
||||
var intermediateResult = goog.result.chain(givenResult, actionCallback);
|
||||
var finalResult = goog.result.chain(intermediateResult, actionCallback);
|
||||
|
||||
assertTrue(goog.result.cancelParentResults(finalResult));
|
||||
assertTrue(finalResult.isCanceled());
|
||||
assertTrue(intermediateResult.isCanceled());
|
||||
assertFalse(givenResult.isCanceled());
|
||||
assertFalse(goog.result.cancelParentResults(finalResult));
|
||||
}
|
||||
|
||||
function testCustomScope() {
|
||||
var scope = {};
|
||||
var finalResult = goog.result.chain(givenResult, actionCallback, scope);
|
||||
goog.result.wait(finalResult, counter);
|
||||
|
||||
givenResult.setValue(1);
|
||||
dependentResult.setValue(2);
|
||||
|
||||
assertEquals(scope, actionCallback.popLastCall().getThis());
|
||||
}
|
||||
|
||||
|
||||
// ASYNCHRONOUS TESTS:
|
||||
|
||||
function testChainAsyncWhenBothResultsSuccess() {
|
||||
var finalResult = goog.result.chain(givenResult, actionCallback);
|
||||
goog.result.wait(finalResult, counter);
|
||||
|
||||
goog.Timer.callOnce(function() { givenResult.setValue(1); });
|
||||
mockClock.tick();
|
||||
|
||||
assertSuccess(actionCallback, givenResult, 1);
|
||||
|
||||
goog.Timer.callOnce(function() { dependentResult.setValue(2); });
|
||||
mockClock.tick();
|
||||
|
||||
assertSuccess(counter, finalResult, 2);
|
||||
}
|
||||
|
||||
function testChainAsyncWhenFirstResultError() {
|
||||
var finalResult = goog.result.chain(givenResult, actionCallback);
|
||||
goog.result.wait(finalResult, counter);
|
||||
|
||||
goog.Timer.callOnce(function() { givenResult.setError(6); });
|
||||
mockClock.tick();
|
||||
|
||||
assertNoCall(actionCallback);
|
||||
assertError(counter, finalResult, 6);
|
||||
}
|
||||
|
||||
function testChainAsyncWhenSecondResultError() {
|
||||
var finalResult = goog.result.chain(givenResult, actionCallback);
|
||||
goog.result.wait(finalResult, counter);
|
||||
|
||||
goog.Timer.callOnce(function() { givenResult.setValue(1); });
|
||||
mockClock.tick();
|
||||
|
||||
assertSuccess(actionCallback, givenResult, 1);
|
||||
|
||||
goog.Timer.callOnce(function() { dependentResult.setError(7); });
|
||||
mockClock.tick();
|
||||
|
||||
assertError(counter, finalResult, 7);
|
||||
}
|
||||
|
||||
function testChainAsyncCancelFirstResult() {
|
||||
var finalResult = goog.result.chain(givenResult, actionCallback);
|
||||
goog.result.wait(finalResult, counter);
|
||||
|
||||
goog.Timer.callOnce(function() {
|
||||
goog.result.cancelParentResults(finalResult);
|
||||
});
|
||||
mockClock.tick();
|
||||
|
||||
assertNoCall(actionCallback);
|
||||
assertTrue(givenResult.isCanceled());
|
||||
assertTrue(finalResult.isCanceled());
|
||||
}
|
||||
|
||||
function testChainAsyncCancelSecondResult() {
|
||||
var finalResult = goog.result.chain(givenResult, actionCallback);
|
||||
goog.result.wait(finalResult, counter);
|
||||
|
||||
goog.Timer.callOnce(function() { givenResult.setValue(1); });
|
||||
mockClock.tick();
|
||||
|
||||
assertSuccess(actionCallback, givenResult, 1);
|
||||
|
||||
goog.Timer.callOnce(function() {
|
||||
goog.result.cancelParentResults(finalResult);
|
||||
});
|
||||
mockClock.tick();
|
||||
|
||||
assertTrue(dependentResult.isCanceled());
|
||||
assertTrue(finalResult.isCanceled());
|
||||
}
|
||||
|
||||
// HELPER FUNCTIONS:
|
||||
|
||||
// Assert that the recordFunction was called once with an argument of
|
||||
// 'result' (the second argument) which has a state of SUCCESS and
|
||||
// a value of 'value' (the third argument).
|
||||
function assertSuccess(recordFunction, result, value) {
|
||||
assertEquals(1, recordFunction.getCallCount());
|
||||
var res = recordFunction.popLastCall().getArgument(0);
|
||||
assertEquals(result, res);
|
||||
assertEquals(goog.result.Result.State.SUCCESS, res.getState());
|
||||
assertEquals(value, res.getValue());
|
||||
}
|
||||
|
||||
// Assert that the recordFunction was called once with an argument of
|
||||
// 'result' (the second argument) which has a state of ERROR.
|
||||
function assertError(recordFunction, result, value) {
|
||||
assertEquals(1, recordFunction.getCallCount());
|
||||
var res = recordFunction.popLastCall().getArgument(0);
|
||||
assertEquals(result, res);
|
||||
assertEquals(goog.result.Result.State.ERROR, res.getState());
|
||||
assertEquals(value, res.getError());
|
||||
}
|
||||
|
||||
// Assert that the recordFunction wasn't called
|
||||
function assertNoCall(recordFunction) {
|
||||
assertEquals(0, recordFunction.getCallCount());
|
||||
}
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,229 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!--
|
||||
Copyright 2012 The Closure Library Authors. All Rights Reserved.
|
||||
|
||||
Use of this source code is governed by the Apache License, Version 2.0.
|
||||
See the COPYING file for details.
|
||||
-->
|
||||
<head>
|
||||
<title>Closure Unit Tests - goog.result.combine</title>
|
||||
<script src="../base.js"></script>
|
||||
<script>
|
||||
|
||||
goog.require('goog.Timer');
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.result');
|
||||
goog.require('goog.testing.MockClock');
|
||||
goog.require('goog.testing.jsunit');
|
||||
goog.require('goog.testing.recordFunction');
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
|
||||
var result1, result2, result3, result4, resultCallback;
|
||||
var combinedResult, successCombinedResult, mockClock;
|
||||
|
||||
function setUpPage() {
|
||||
mockClock = new goog.testing.MockClock();
|
||||
mockClock.install();
|
||||
}
|
||||
|
||||
function tearDownPage() {
|
||||
goog.dispose(mockClock);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
mockClock.reset();
|
||||
result1 = new goog.result.SimpleResult();
|
||||
result2 = new goog.result.SimpleResult();
|
||||
result3 = new goog.result.SimpleResult();
|
||||
result4 = new goog.result.SimpleResult();
|
||||
|
||||
combinedResult = goog.result.combine(result1, result2, result3, result4);
|
||||
|
||||
successCombinedResult =
|
||||
goog.result.combineOnSuccess(result1, result2, result3, result4);
|
||||
|
||||
resultCallback = goog.testing.recordFunction();
|
||||
}
|
||||
|
||||
function tearDown() {
|
||||
result1 = result2 = result3 = result4 = resultCallback = null;
|
||||
combinedResult = successCombinedResult = null;
|
||||
}
|
||||
|
||||
function testSynchronousCombine() {
|
||||
resolveAllGivenResultsToSuccess();
|
||||
|
||||
newCombinedResult = goog.result.combine(result1, result2, result3, result4);
|
||||
|
||||
goog.result.wait(newCombinedResult, resultCallback);
|
||||
|
||||
assertSuccessCall(newCombinedResult, resultCallback);
|
||||
}
|
||||
|
||||
function testCombineWhenAllResultsSuccess() {
|
||||
goog.result.wait(combinedResult, resultCallback);
|
||||
|
||||
resolveAllGivenResultsToSuccess();
|
||||
|
||||
assertSuccessCall(combinedResult, resultCallback);
|
||||
}
|
||||
|
||||
function testAsyncCombineWhenAllResultsSuccess() {
|
||||
goog.result.wait(combinedResult, resultCallback);
|
||||
|
||||
goog.Timer.callOnce(function() { resolveAllGivenResultsToSuccess(); });
|
||||
mockClock.tick();
|
||||
|
||||
assertSuccessCall(combinedResult, resultCallback);
|
||||
}
|
||||
|
||||
function testCombineWhenAllResultsFail() {
|
||||
goog.result.wait(combinedResult, resultCallback);
|
||||
|
||||
resolveAllGivenResultsToError();
|
||||
|
||||
assertSuccessCall(combinedResult, resultCallback);
|
||||
}
|
||||
|
||||
function testAsyncCombineWhenAllResultsFail() {
|
||||
goog.result.wait(combinedResult, resultCallback);
|
||||
|
||||
goog.Timer.callOnce(function() { resolveAllGivenResultsToError(); });
|
||||
mockClock.tick();
|
||||
|
||||
assertSuccessCall(combinedResult, resultCallback);
|
||||
}
|
||||
|
||||
function testCombineWhenSomeResultsSuccess() {
|
||||
goog.result.wait(combinedResult, resultCallback);
|
||||
|
||||
resolveSomeGivenResultsToSuccess();
|
||||
|
||||
assertSuccessCall(combinedResult, resultCallback);
|
||||
}
|
||||
|
||||
function testAsyncCombineWhenSomeResultsSuccess() {
|
||||
goog.result.wait(combinedResult, resultCallback);
|
||||
|
||||
goog.Timer.callOnce(function() { resolveSomeGivenResultsToSuccess(); });
|
||||
mockClock.tick();
|
||||
|
||||
assertSuccessCall(combinedResult, resultCallback);
|
||||
}
|
||||
|
||||
function testCombineOnSuccessWhenAllResultsSuccess() {
|
||||
goog.result.wait(successCombinedResult, resultCallback);
|
||||
|
||||
resolveAllGivenResultsToSuccess();
|
||||
|
||||
assertSuccessCall(successCombinedResult, resultCallback);
|
||||
}
|
||||
|
||||
function testAsyncCombineOnSuccessWhenAllResultsSuccess() {
|
||||
goog.result.wait(successCombinedResult, resultCallback);
|
||||
|
||||
goog.Timer.callOnce(function() { resolveAllGivenResultsToSuccess(); });
|
||||
mockClock.tick();
|
||||
|
||||
assertSuccessCall(successCombinedResult, resultCallback);
|
||||
}
|
||||
|
||||
function testCombineOnSuccessWhenAllResultsFail() {
|
||||
goog.result.wait(successCombinedResult, resultCallback);
|
||||
|
||||
resolveAllGivenResultsToError();
|
||||
|
||||
assertErrorCall(successCombinedResult, resultCallback);
|
||||
}
|
||||
|
||||
function testAsyncCombineOnSuccessWhenAllResultsFail() {
|
||||
goog.result.wait(successCombinedResult, resultCallback);
|
||||
|
||||
goog.Timer.callOnce(function() { resolveAllGivenResultsToError(); });
|
||||
mockClock.tick();
|
||||
|
||||
assertErrorCall(successCombinedResult, resultCallback);
|
||||
}
|
||||
|
||||
function testCombineOnSuccessWhenSomeResultsSuccess() {
|
||||
goog.result.wait(successCombinedResult, resultCallback);
|
||||
|
||||
resolveSomeGivenResultsToSuccess();
|
||||
|
||||
assertErrorCall(successCombinedResult, resultCallback);
|
||||
}
|
||||
|
||||
function testAsyncCombineOnSuccessWhenSomeResultsSuccess() {
|
||||
goog.result.wait(successCombinedResult, resultCallback);
|
||||
|
||||
goog.Timer.callOnce(function() { resolveSomeGivenResultsToSuccess(); });
|
||||
mockClock.tick();
|
||||
|
||||
assertErrorCall(successCombinedResult, resultCallback);
|
||||
}
|
||||
|
||||
function testCancelParentResults() {
|
||||
goog.result.wait(combinedResult, resultCallback);
|
||||
|
||||
goog.result.cancelParentResults(combinedResult);
|
||||
|
||||
assertArgumentContainsGivenResults(combinedResult.getValue())
|
||||
goog.array.forEach([result1, result2, result3, result4],
|
||||
function(result) {
|
||||
assertTrue(result.isCanceled());
|
||||
});
|
||||
}
|
||||
|
||||
function assertSuccessCall(combinedResult, resultCallback) {
|
||||
assertEquals(goog.result.Result.State.SUCCESS, combinedResult.getState());
|
||||
assertEquals(1, resultCallback.getCallCount());
|
||||
|
||||
var result = resultCallback.popLastCall().getArgument(0);
|
||||
assertEquals(combinedResult, result);
|
||||
assertArgumentContainsGivenResults(result.getValue());
|
||||
}
|
||||
|
||||
function assertErrorCall(combinedResult, resultCallback) {
|
||||
assertEquals(goog.result.Result.State.ERROR,
|
||||
combinedResult.getState());
|
||||
assertEquals(1, resultCallback.getCallCount());
|
||||
|
||||
var result = resultCallback.popLastCall().getArgument(0);
|
||||
assertEquals(combinedResult, result);
|
||||
assertArgumentContainsGivenResults(combinedResult.getError());
|
||||
}
|
||||
|
||||
function assertArgumentContainsGivenResults(resultsArray) {
|
||||
assertEquals(4, resultsArray.length);
|
||||
|
||||
goog.array.forEach([result1, result2, result3, result4], function(res) {
|
||||
assertTrue(goog.array.contains(resultsArray, res));
|
||||
});
|
||||
}
|
||||
|
||||
function resolveAllGivenResultsToSuccess() {
|
||||
goog.array.forEach([result1, result2, result3, result4], function(res) {
|
||||
res.setValue(1);
|
||||
});
|
||||
}
|
||||
|
||||
function resolveAllGivenResultsToError() {
|
||||
goog.array.forEach([result1, result2, result3, result4], function(res) {
|
||||
res.setError();
|
||||
});
|
||||
}
|
||||
|
||||
function resolveSomeGivenResultsToSuccess() {
|
||||
goog.array.forEach([result2, result3, result4], function(res) {
|
||||
res.setValue(1);
|
||||
});
|
||||
result1.setError();
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,59 @@
|
||||
// Copyright 2012 The Closure Library Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS-IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/**
|
||||
* @fileoverview An adaptor from a Result to a Deferred.
|
||||
*
|
||||
* TODO (vbhasin): cancel() support.
|
||||
* TODO (vbhasin): See if we can make this a static.
|
||||
* TODO (gboyer, vbhasin): Rename to "Adapter" once this graduates; this is the
|
||||
* proper programmer spelling.
|
||||
*/
|
||||
|
||||
|
||||
goog.provide('goog.result.DeferredAdaptor');
|
||||
|
||||
goog.require('goog.async.Deferred');
|
||||
goog.require('goog.result');
|
||||
goog.require('goog.result.Result');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* An adaptor from Result to a Deferred, for use with existing Deferred chains.
|
||||
*
|
||||
* @param {!goog.result.Result} result A result.
|
||||
* @constructor
|
||||
* @extends {goog.async.Deferred}
|
||||
* @final
|
||||
* @deprecated Use {@link goog.Promise} instead - http://go/promisemigration
|
||||
*/
|
||||
goog.result.DeferredAdaptor = function(result) {
|
||||
goog.result.DeferredAdaptor.base(this, 'constructor');
|
||||
goog.result.wait(result, function(result) {
|
||||
if (this.hasFired()) {
|
||||
return;
|
||||
}
|
||||
if (result.getState() == goog.result.Result.State.SUCCESS) {
|
||||
this.callback(result.getValue());
|
||||
} else if (result.getState() == goog.result.Result.State.ERROR) {
|
||||
if (result.getError() instanceof goog.result.Result.CancelError) {
|
||||
this.cancel();
|
||||
} else {
|
||||
this.errback(result.getError());
|
||||
}
|
||||
}
|
||||
}, this);
|
||||
};
|
||||
goog.inherits(goog.result.DeferredAdaptor, goog.async.Deferred);
|
||||
@@ -0,0 +1,86 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!--
|
||||
Copyright 2012 The Closure Library Authors. All Rights Reserved.
|
||||
|
||||
Use of this source code is governed by the Apache License, Version 2.0.
|
||||
See the COPYING file for details.
|
||||
-->
|
||||
<head>
|
||||
<title>Closure Unit Tests - goog.result.DeferredAdaptor</title>
|
||||
<script src="../base.js"></script>
|
||||
<script>
|
||||
|
||||
goog.require('goog.result');
|
||||
goog.require('goog.result.DeferredAdaptor');
|
||||
goog.require('goog.result.SimpleResult');
|
||||
goog.require('goog.testing.jsunit');
|
||||
goog.require('goog.testing.recordFunction');
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
|
||||
var result, deferred, record;
|
||||
|
||||
function setUp() {
|
||||
result = new goog.result.SimpleResult();
|
||||
deferred = new goog.result.DeferredAdaptor(result);
|
||||
record = new goog.testing.recordFunction();
|
||||
}
|
||||
|
||||
function tearDown() {
|
||||
result = deferred = record = null;
|
||||
}
|
||||
|
||||
function testResultSuccesfulResolution() {
|
||||
deferred.addCallback(record);
|
||||
result.setValue(1);
|
||||
assertEquals(1, record.getCallCount());
|
||||
var call = record.popLastCall();
|
||||
assertEquals(1, call.getArgument(0));
|
||||
}
|
||||
|
||||
function testResultErrorResolution() {
|
||||
deferred.addErrback(record);
|
||||
result.setError(2);
|
||||
assertEquals(1, record.getCallCount());
|
||||
var call = record.popLastCall();
|
||||
assertEquals(2, call.getArgument(0));
|
||||
}
|
||||
|
||||
function testResultCancelResolution() {
|
||||
deferred.addCallback(record);
|
||||
var cancelCallback = new goog.testing.recordFunction();
|
||||
deferred.addErrback(cancelCallback);
|
||||
result.cancel();
|
||||
assertEquals(0, record.getCallCount());
|
||||
assertEquals(1, cancelCallback.getCallCount());
|
||||
var call = cancelCallback.popLastCall();
|
||||
assertTrue(call.getArgument(0) instanceof
|
||||
goog.async.Deferred.CanceledError);
|
||||
}
|
||||
|
||||
function testAddCallbackOnResolvedResult() {
|
||||
result.setValue(1);
|
||||
assertEquals(1, result.getValue());
|
||||
deferred.addCallback(record);
|
||||
|
||||
// callback should be called immediately when result is already resolved.
|
||||
assertEquals(1, record.getCallCount());
|
||||
assertEquals(1, record.popLastCall().getArgument(0));
|
||||
}
|
||||
|
||||
function testAddErrbackOnErroredResult() {
|
||||
result.setError(1);
|
||||
assertEquals(1, result.getError());
|
||||
|
||||
// errback should be called immediately when result already errored.
|
||||
deferred.addErrback(record);
|
||||
assertEquals(1, record.getCallCount());
|
||||
assertEquals(1, record.popLastCall().getArgument(0));
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,45 @@
|
||||
// Copyright 2012 The Closure Library Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS-IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/**
|
||||
* @fileoverview An interface for Results whose eventual value depends on the
|
||||
* value of one or more other Results.
|
||||
*/
|
||||
|
||||
goog.provide('goog.result.DependentResult');
|
||||
|
||||
goog.require('goog.result.Result');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A DependentResult represents a Result whose eventual value depends on the
|
||||
* value of one or more other Results. For example, the Result returned by
|
||||
* @see goog.result.chain or @see goog.result.combine is dependent on the
|
||||
* Results given as arguments.
|
||||
* @interface
|
||||
* @extends {goog.result.Result}
|
||||
* @deprecated Use {@link goog.Promise} instead - http://go/promisemigration
|
||||
*/
|
||||
goog.result.DependentResult = function() {};
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @return {!Array<!goog.result.Result>} A list of Results which will affect
|
||||
* the eventual value of this Result. The returned Results may themselves
|
||||
* have parent results, which would be grandparents of this Result;
|
||||
* grandparents (and any other ancestors) are not included in this list.
|
||||
*/
|
||||
goog.result.DependentResult.prototype.getParentResults = function() {};
|
||||
@@ -0,0 +1,119 @@
|
||||
// Copyright 2012 The Closure Library Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS-IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/**
|
||||
* @fileoverview Defines an interface that represents a Result.
|
||||
*
|
||||
* NOTE: goog.result is soft deprecated - we expect to replace this and
|
||||
* {@link goog.async.Deferred} with {@link goog.Promise}.
|
||||
*/
|
||||
|
||||
goog.provide('goog.result.Result');
|
||||
|
||||
goog.require('goog.Thenable');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A Result object represents a value returned by an asynchronous
|
||||
* operation at some point in the future (e.g. a network fetch). This is akin
|
||||
* to a 'Promise' or a 'Future' in other languages and frameworks.
|
||||
*
|
||||
* @interface
|
||||
* @extends {goog.Thenable}
|
||||
* @deprecated Use {@link goog.Promise} instead - http://go/promisemigration
|
||||
*/
|
||||
goog.result.Result = function() {};
|
||||
|
||||
|
||||
/**
|
||||
* Attaches handlers to be called when the value of this Result is available.
|
||||
* Handlers are called in the order they were added by wait.
|
||||
*
|
||||
* @param {!function(this:T, !goog.result.Result)} handler The function called
|
||||
* when the value is available. The function is passed the Result object as
|
||||
* the only argument.
|
||||
* @param {T=} opt_scope Optional scope for the handler.
|
||||
* @template T
|
||||
*/
|
||||
goog.result.Result.prototype.wait = function(handler, opt_scope) {};
|
||||
|
||||
|
||||
/**
|
||||
* The States this object can be in.
|
||||
*
|
||||
* @enum {string}
|
||||
* @deprecated Use {@link goog.Promise} instead - http://go/promisemigration
|
||||
*/
|
||||
goog.result.Result.State = {
|
||||
/** The operation was a success and the value is available. */
|
||||
SUCCESS: 'success',
|
||||
|
||||
/** The operation resulted in an error. */
|
||||
ERROR: 'error',
|
||||
|
||||
/** The operation is incomplete and the value is not yet available. */
|
||||
PENDING: 'pending'
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {!goog.result.Result.State} The state of this Result.
|
||||
*/
|
||||
goog.result.Result.prototype.getState = function() {};
|
||||
|
||||
|
||||
/**
|
||||
* @return {*} The value of this Result. Will return undefined if the Result is
|
||||
* pending or was an error.
|
||||
*/
|
||||
goog.result.Result.prototype.getValue = function() {};
|
||||
|
||||
|
||||
/**
|
||||
* @return {*} The error slug for this Result. Will return undefined if the
|
||||
* Result was a success, the error slug was not set, or if the Result is
|
||||
* pending.
|
||||
*/
|
||||
goog.result.Result.prototype.getError = function() {};
|
||||
|
||||
|
||||
/**
|
||||
* Cancels the current Result, invoking the canceler function, if set.
|
||||
*
|
||||
* @return {boolean} Whether the Result was canceled.
|
||||
*/
|
||||
goog.result.Result.prototype.cancel = function() {};
|
||||
|
||||
|
||||
/**
|
||||
* @return {boolean} Whether this Result was canceled.
|
||||
*/
|
||||
goog.result.Result.prototype.isCanceled = function() {};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* The value to be passed to the error handlers invoked upon cancellation.
|
||||
* @constructor
|
||||
* @extends {Error}
|
||||
* @final
|
||||
* @deprecated Use {@link goog.Promise} instead - http://go/promisemigration
|
||||
*/
|
||||
goog.result.Result.CancelError = function() {
|
||||
// Note that this does not derive from goog.debug.Error in order to prevent
|
||||
// stack trace capture and reduce the amount of garbage generated during a
|
||||
// cancel() operation.
|
||||
};
|
||||
goog.inherits(goog.result.Result.CancelError, Error);
|
||||
@@ -0,0 +1,556 @@
|
||||
// Copyright 2012 The Closure Library Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS-IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/**
|
||||
* @fileoverview This file provides primitives and tools (wait, transform,
|
||||
* chain, combine) that make it easier to work with Results. This section
|
||||
* gives an overview of their functionality along with some examples and the
|
||||
* actual definitions have detailed descriptions next to them.
|
||||
*
|
||||
*
|
||||
* NOTE: goog.result is soft deprecated - we expect to replace this and
|
||||
* goog.async.Deferred with a wrapper around W3C Promises:
|
||||
* http://dom.spec.whatwg.org/#promises.
|
||||
*/
|
||||
|
||||
goog.provide('goog.result');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.result.DependentResult');
|
||||
goog.require('goog.result.Result');
|
||||
goog.require('goog.result.SimpleResult');
|
||||
|
||||
|
||||
/**
|
||||
* Returns a successful result containing the provided value.
|
||||
*
|
||||
* Example:
|
||||
* <pre>
|
||||
*
|
||||
* var value = 'some-value';
|
||||
* var result = goog.result.immediateResult(value);
|
||||
* assertEquals(goog.result.Result.State.SUCCESS, result.getState());
|
||||
* assertEquals(value, result.getValue());
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @param {*} value The value of the result.
|
||||
* @return {!goog.result.Result} A Result object that has already been resolved
|
||||
* to the supplied value.
|
||||
*/
|
||||
goog.result.successfulResult = function(value) {
|
||||
var result = new goog.result.SimpleResult();
|
||||
result.setValue(value);
|
||||
return result;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns a failed result with the optional error slug set.
|
||||
*
|
||||
* Example:
|
||||
* <pre>
|
||||
*
|
||||
* var error = new Error('something-failed');
|
||||
* var result = goog.result.failedResult(error);
|
||||
* assertEquals(goog.result.Result.State.ERROR, result.getState());
|
||||
* assertEquals(error, result.getError());
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @param {*=} opt_error The error to which the result should resolve.
|
||||
* @return {!goog.result.Result} A Result object that has already been resolved
|
||||
* to the supplied Error.
|
||||
*/
|
||||
goog.result.failedResult = function(opt_error) {
|
||||
var result = new goog.result.SimpleResult();
|
||||
result.setError(opt_error);
|
||||
return result;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns a canceled result.
|
||||
* The result will be resolved to an error of type CancelError.
|
||||
*
|
||||
* Example:
|
||||
* <pre>
|
||||
*
|
||||
* var result = goog.result.canceledResult();
|
||||
* assertEquals(goog.result.Result.State.ERROR, result.getState());
|
||||
* var error = result.getError();
|
||||
* assertTrue(error instanceof goog.result.Result.CancelError);
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @return {!goog.result.Result} A canceled Result.
|
||||
*/
|
||||
goog.result.canceledResult = function() {
|
||||
var result = new goog.result.SimpleResult();
|
||||
result.cancel();
|
||||
return result;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Calls the handler on resolution of the result (success or failure).
|
||||
* The handler is passed the result object as the only parameter. The call will
|
||||
* be immediate if the result is no longer pending.
|
||||
*
|
||||
* Example:
|
||||
* <pre>
|
||||
*
|
||||
* var result = xhr.get('testdata/xhr_test_text.data');
|
||||
*
|
||||
* // Wait for the result to be resolved and alert it's state.
|
||||
* goog.result.wait(result, function(result) {
|
||||
* alert('State: ' + result.getState());
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
* @param {!goog.result.Result} result The result to install the handlers.
|
||||
* @param {function(this:T, !goog.result.Result)} handler The handler to be
|
||||
* called. The handler is passed the result object as the only parameter.
|
||||
* @param {T=} opt_scope Optional scope for the handler.
|
||||
* @template T
|
||||
*/
|
||||
goog.result.wait = function(result, handler, opt_scope) {
|
||||
result.wait(handler, opt_scope);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Calls the handler if the result succeeds. The result object is the only
|
||||
* parameter passed to the handler. The call will be immediate if the result
|
||||
* has already succeeded.
|
||||
*
|
||||
* Example:
|
||||
* <pre>
|
||||
*
|
||||
* var result = xhr.get('testdata/xhr_test_text.data');
|
||||
*
|
||||
* // attach a success handler.
|
||||
* goog.result.waitOnSuccess(result, function(resultValue, result) {
|
||||
* var datavalue = result.getvalue();
|
||||
* alert('value: ' + datavalue + ' == ' + resultValue);
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
* @param {!goog.result.Result} result The result to install the handlers.
|
||||
* @param {function(this:T, ?, !goog.result.Result)} handler The handler to be
|
||||
* called. The handler is passed the result value and the result as
|
||||
* parameters.
|
||||
* @param {T=} opt_scope Optional scope for the handler.
|
||||
* @template T
|
||||
*/
|
||||
goog.result.waitOnSuccess = function(result, handler, opt_scope) {
|
||||
goog.result.wait(result, function(res) {
|
||||
if (res.getState() == goog.result.Result.State.SUCCESS) {
|
||||
// 'this' refers to opt_scope
|
||||
handler.call(this, res.getValue(), res);
|
||||
}
|
||||
}, opt_scope);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Calls the handler if the result action errors. The result object is passed as
|
||||
* the only parameter to the handler. The call will be immediate if the result
|
||||
* object has already resolved to an error.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* var result = xhr.get('testdata/xhr_test_text.data');
|
||||
*
|
||||
* // Attach a failure handler.
|
||||
* goog.result.waitOnError(result, function(error) {
|
||||
* // Failed asynchronous call!
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
* @param {!goog.result.Result} result The result to install the handlers.
|
||||
* @param {function(this:T, ?, !goog.result.Result)} handler The handler to be
|
||||
* called. The handler is passed the error and the result object as
|
||||
* parameters.
|
||||
* @param {T=} opt_scope Optional scope for the handler.
|
||||
* @template T
|
||||
*/
|
||||
goog.result.waitOnError = function(result, handler, opt_scope) {
|
||||
goog.result.wait(result, function(res) {
|
||||
if (res.getState() == goog.result.Result.State.ERROR) {
|
||||
// 'this' refers to opt_scope
|
||||
handler.call(this, res.getError(), res);
|
||||
}
|
||||
}, opt_scope);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Given a result and a transform function, returns a new result whose value,
|
||||
* on success, will be the value of the given result after having been passed
|
||||
* through the transform function.
|
||||
*
|
||||
* If the given result is an error, the returned result is also an error and the
|
||||
* transform will not be called.
|
||||
*
|
||||
* Example:
|
||||
* <pre>
|
||||
*
|
||||
* var result = xhr.getJson('testdata/xhr_test_json.data');
|
||||
*
|
||||
* // Transform contents of returned data using 'processJson' and create a
|
||||
* // transformed result to use returned JSON.
|
||||
* var transformedResult = goog.result.transform(result, processJson);
|
||||
*
|
||||
* // Attach success and failure handlers to the tranformed result.
|
||||
* goog.result.waitOnSuccess(transformedResult, function(resultValue, result) {
|
||||
* var jsonData = resultValue;
|
||||
* assertEquals('ok', jsonData['stat']);
|
||||
* });
|
||||
*
|
||||
* goog.result.waitOnError(transformedResult, function(error) {
|
||||
* // Failed getJson call
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
* @param {!goog.result.Result} result The result whose value will be
|
||||
* transformed.
|
||||
* @param {function(?):?} transformer The transformer
|
||||
* function. The return value of this function will become the value of the
|
||||
* returned result.
|
||||
*
|
||||
* @return {!goog.result.DependentResult} A new Result whose eventual value will
|
||||
* be the returned value of the transformer function.
|
||||
*/
|
||||
goog.result.transform = function(result, transformer) {
|
||||
var returnedResult = new goog.result.DependentResultImpl_([result]);
|
||||
|
||||
goog.result.wait(result, function(res) {
|
||||
if (res.getState() == goog.result.Result.State.SUCCESS) {
|
||||
returnedResult.setValue(transformer(res.getValue()));
|
||||
} else {
|
||||
returnedResult.setError(res.getError());
|
||||
}
|
||||
});
|
||||
|
||||
return returnedResult;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* The chain function aids in chaining of asynchronous Results. This provides a
|
||||
* convenience for use cases where asynchronous operations must happen serially
|
||||
* i.e. subsequent asynchronous operations are dependent on data returned by
|
||||
* prior asynchronous operations.
|
||||
*
|
||||
* It accepts a result and an action callback as arguments and returns a
|
||||
* result. The action callback is called when the first result succeeds and is
|
||||
* supposed to return a second result. The returned result is resolved when one
|
||||
* of both of the results resolve (depending on their success or failure.) The
|
||||
* state and value of the returned result in the various cases is documented
|
||||
* below:
|
||||
* <pre>
|
||||
*
|
||||
* First Result State: Second Result State: Returned Result State:
|
||||
* SUCCESS SUCCESS SUCCESS
|
||||
* SUCCESS ERROR ERROR
|
||||
* ERROR Not created ERROR
|
||||
* </pre>
|
||||
*
|
||||
* The value of the returned result, in the case both results succeed, is the
|
||||
* value of the second result (the result returned by the action callback.)
|
||||
*
|
||||
* Example:
|
||||
* <pre>
|
||||
*
|
||||
* var testDataResult = xhr.get('testdata/xhr_test_text.data');
|
||||
*
|
||||
* // Chain this result to perform another asynchronous operation when this
|
||||
* // Result is resolved.
|
||||
* var chainedResult = goog.result.chain(testDataResult,
|
||||
* function(testDataResult) {
|
||||
*
|
||||
* // The result value of testDataResult is the URL for JSON data.
|
||||
* var jsonDataUrl = testDataResult.getValue();
|
||||
*
|
||||
* // Create a new Result object when the original result is resolved.
|
||||
* var jsonResult = xhr.getJson(jsonDataUrl);
|
||||
*
|
||||
* // Return the newly created Result.
|
||||
* return jsonResult;
|
||||
* });
|
||||
*
|
||||
* // The chained result resolves to success when both results resolve to
|
||||
* // success.
|
||||
* goog.result.waitOnSuccess(chainedResult, function(resultValue, result) {
|
||||
*
|
||||
* // At this point, both results have succeeded and we can use the JSON
|
||||
* // data returned by the second asynchronous call.
|
||||
* var jsonData = resultValue;
|
||||
* assertEquals('ok', jsonData['stat']);
|
||||
* });
|
||||
*
|
||||
* // Attach the error handler to be called when either Result fails.
|
||||
* goog.result.waitOnError(chainedResult, function(result) {
|
||||
* alert('chained result failed!');
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
* @param {!goog.result.Result} result The result to chain.
|
||||
* @param {function(this:T, !goog.result.Result):!goog.result.Result}
|
||||
* actionCallback The callback called when the result is resolved. This
|
||||
* callback must return a Result.
|
||||
* @param {T=} opt_scope Optional scope for the action callback.
|
||||
* @return {!goog.result.DependentResult} A result that is resolved when both
|
||||
* the given Result and the Result returned by the actionCallback have
|
||||
* resolved.
|
||||
* @template T
|
||||
*/
|
||||
goog.result.chain = function(result, actionCallback, opt_scope) {
|
||||
var dependentResult = new goog.result.DependentResultImpl_([result]);
|
||||
|
||||
// Wait for the first action.
|
||||
goog.result.wait(result, function(result) {
|
||||
if (result.getState() == goog.result.Result.State.SUCCESS) {
|
||||
|
||||
// The first action succeeded. Chain the contingent action.
|
||||
var contingentResult = actionCallback.call(opt_scope, result);
|
||||
dependentResult.addParentResult(contingentResult);
|
||||
goog.result.wait(contingentResult, function(contingentResult) {
|
||||
|
||||
// The contingent action completed. Set the dependent result based on
|
||||
// the contingent action's outcome.
|
||||
if (contingentResult.getState() ==
|
||||
goog.result.Result.State.SUCCESS) {
|
||||
dependentResult.setValue(contingentResult.getValue());
|
||||
} else {
|
||||
dependentResult.setError(contingentResult.getError());
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// First action failed, the dependent result should also fail.
|
||||
dependentResult.setError(result.getError());
|
||||
}
|
||||
});
|
||||
|
||||
return dependentResult;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns a result that waits on all given results to resolve. Once all have
|
||||
* resolved, the returned result will succeed (and never error).
|
||||
*
|
||||
* Example:
|
||||
* <pre>
|
||||
*
|
||||
* var result1 = xhr.get('testdata/xhr_test_text.data');
|
||||
*
|
||||
* // Get a second independent Result.
|
||||
* var result2 = xhr.getJson('testdata/xhr_test_json.data');
|
||||
*
|
||||
* // Create a Result that resolves when both prior results resolve.
|
||||
* var combinedResult = goog.result.combine(result1, result2);
|
||||
*
|
||||
* // Process data after resolution of both results.
|
||||
* goog.result.waitOnSuccess(combinedResult, function(results) {
|
||||
* goog.array.forEach(results, function(result) {
|
||||
* alert(result.getState());
|
||||
* });
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
* @param {...!goog.result.Result} var_args The results to wait on.
|
||||
*
|
||||
* @return {!goog.result.DependentResult} A new Result whose eventual value will
|
||||
* be the resolved given Result objects.
|
||||
*/
|
||||
goog.result.combine = function(var_args) {
|
||||
/** @type {!Array<!goog.result.Result>} */
|
||||
var results = goog.array.clone(arguments);
|
||||
var combinedResult = new goog.result.DependentResultImpl_(results);
|
||||
|
||||
var isResolved = function(res) {
|
||||
return res.getState() != goog.result.Result.State.PENDING;
|
||||
};
|
||||
|
||||
var checkResults = function() {
|
||||
if (combinedResult.getState() == goog.result.Result.State.PENDING &&
|
||||
goog.array.every(results, isResolved)) {
|
||||
combinedResult.setValue(results);
|
||||
}
|
||||
};
|
||||
|
||||
goog.array.forEach(results, function(result) {
|
||||
goog.result.wait(result, checkResults);
|
||||
});
|
||||
|
||||
return combinedResult;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns a result that waits on all given results to resolve. Once all have
|
||||
* resolved, the returned result will succeed if and only if all given results
|
||||
* succeeded. Otherwise it will error.
|
||||
*
|
||||
* Example:
|
||||
* <pre>
|
||||
*
|
||||
* var result1 = xhr.get('testdata/xhr_test_text.data');
|
||||
*
|
||||
* // Get a second independent Result.
|
||||
* var result2 = xhr.getJson('testdata/xhr_test_json.data');
|
||||
*
|
||||
* // Create a Result that resolves when both prior results resolve.
|
||||
* var combinedResult = goog.result.combineOnSuccess(result1, result2);
|
||||
*
|
||||
* // Process data after successful resolution of both results.
|
||||
* goog.result.waitOnSuccess(combinedResult, function(results) {
|
||||
* var textData = results[0].getValue();
|
||||
* var jsonData = results[1].getValue();
|
||||
* assertEquals('Just some data.', textData);
|
||||
* assertEquals('ok', jsonData['stat']);
|
||||
* });
|
||||
*
|
||||
* // Handle errors when either or both results failed.
|
||||
* goog.result.waitOnError(combinedResult, function(combined) {
|
||||
* var results = combined.getError();
|
||||
*
|
||||
* if (results[0].getState() == goog.result.Result.State.ERROR) {
|
||||
* alert('result1 failed');
|
||||
* }
|
||||
*
|
||||
* if (results[1].getState() == goog.result.Result.State.ERROR) {
|
||||
* alert('result2 failed');
|
||||
* }
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
* @param {...!goog.result.Result} var_args The results to wait on.
|
||||
*
|
||||
* @return {!goog.result.DependentResult} A new Result whose eventual value will
|
||||
* be an array of values of the given Result objects.
|
||||
*/
|
||||
goog.result.combineOnSuccess = function(var_args) {
|
||||
var results = goog.array.clone(arguments);
|
||||
var combinedResult = new goog.result.DependentResultImpl_(results);
|
||||
|
||||
var resolvedSuccessfully = function(res) {
|
||||
return res.getState() == goog.result.Result.State.SUCCESS;
|
||||
};
|
||||
|
||||
goog.result.wait(
|
||||
goog.result.combine.apply(goog.result.combine, results),
|
||||
// The combined result never ERRORs
|
||||
function(res) {
|
||||
var results = /** @type {Array<!goog.result.Result>} */ (
|
||||
res.getValue());
|
||||
if (goog.array.every(results, resolvedSuccessfully)) {
|
||||
combinedResult.setValue(results);
|
||||
} else {
|
||||
combinedResult.setError(results);
|
||||
}
|
||||
});
|
||||
|
||||
return combinedResult;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Given a DependentResult, cancels the Results it depends on (that is, the
|
||||
* results returned by getParentResults). This function does not recurse,
|
||||
* so e.g. parents of parents are not canceled; only the immediate parents of
|
||||
* the given Result are canceled.
|
||||
*
|
||||
* Example using @see goog.result.combine:
|
||||
* <pre>
|
||||
* var result1 = xhr.get('testdata/xhr_test_text.data');
|
||||
*
|
||||
* // Get a second independent Result.
|
||||
* var result2 = xhr.getJson('testdata/xhr_test_json.data');
|
||||
*
|
||||
* // Create a Result that resolves when both prior results resolve.
|
||||
* var combinedResult = goog.result.combineOnSuccess(result1, result2);
|
||||
*
|
||||
* combinedResult.wait(function() {
|
||||
* if (combinedResult.isCanceled()) {
|
||||
* goog.result.cancelParentResults(combinedResult);
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* // Now, canceling combinedResult will cancel both result1 and result2.
|
||||
* combinedResult.cancel();
|
||||
* </pre>
|
||||
* @param {!goog.result.DependentResult} dependentResult A Result that is
|
||||
* dependent on the values of other Results (for example the Result of a
|
||||
* goog.result.combine, goog.result.chain, or goog.result.transform call).
|
||||
* @return {boolean} True if any results were successfully canceled; otherwise
|
||||
* false.
|
||||
* TODO(user): Implement a recursive version of this that cancels all
|
||||
* ancestor results.
|
||||
*/
|
||||
goog.result.cancelParentResults = function(dependentResult) {
|
||||
var anyCanceled = false;
|
||||
var results = dependentResult.getParentResults();
|
||||
for (var n = 0; n < results.length; n++) {
|
||||
anyCanceled |= results[n].cancel();
|
||||
}
|
||||
return !!anyCanceled;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A DependentResult represents a Result whose eventual value depends on the
|
||||
* value of one or more other Results. For example, the Result returned by
|
||||
* @see goog.result.chain or @see goog.result.combine is dependent on the
|
||||
* Results given as arguments.
|
||||
*
|
||||
* @param {!Array<!goog.result.Result>} parentResults A list of Results that
|
||||
* will affect the eventual value of this Result.
|
||||
* @constructor
|
||||
* @implements {goog.result.DependentResult}
|
||||
* @extends {goog.result.SimpleResult}
|
||||
* @private
|
||||
*/
|
||||
goog.result.DependentResultImpl_ = function(parentResults) {
|
||||
goog.result.DependentResultImpl_.base(this, 'constructor');
|
||||
/**
|
||||
* A list of Results that will affect the eventual value of this Result.
|
||||
* @type {!Array<!goog.result.Result>}
|
||||
* @private
|
||||
*/
|
||||
this.parentResults_ = parentResults;
|
||||
};
|
||||
goog.inherits(goog.result.DependentResultImpl_, goog.result.SimpleResult);
|
||||
|
||||
|
||||
/**
|
||||
* Adds a Result to the list of Results that affect this one.
|
||||
* @param {!goog.result.Result} parentResult A result whose value affects the
|
||||
* value of this Result.
|
||||
*/
|
||||
goog.result.DependentResultImpl_.prototype.addParentResult = function(
|
||||
parentResult) {
|
||||
this.parentResults_.push(parentResult);
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.result.DependentResultImpl_.prototype.getParentResults = function() {
|
||||
return this.parentResults_;
|
||||
};
|
||||
@@ -0,0 +1,46 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!--
|
||||
Copyright 2012 The Closure Library Authors. All Rights Reserved.
|
||||
|
||||
Use of this source code is governed by the Apache License, Version 2.0.
|
||||
See the COPYING file for details.
|
||||
-->
|
||||
<head>
|
||||
<title>Closure Unit Tests - goog.result.*</title>
|
||||
<script src="../base.js"></script>
|
||||
<script>
|
||||
goog.require('goog.result');
|
||||
goog.require('goog.testing.jsunit');
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
|
||||
function testSuccessfulResult() {
|
||||
var value = 'some-value';
|
||||
var result = goog.result.successfulResult(value);
|
||||
assertEquals(goog.result.Result.State.SUCCESS, result.getState());
|
||||
assertEquals(value, result.getValue());
|
||||
}
|
||||
|
||||
|
||||
function testFailedResult() {
|
||||
var error = new Error('something-failed');
|
||||
var result = goog.result.failedResult(error);
|
||||
assertEquals(goog.result.Result.State.ERROR, result.getState());
|
||||
assertEquals(error, result.getError());
|
||||
}
|
||||
|
||||
|
||||
function testCanceledResult() {
|
||||
var result = goog.result.canceledResult();
|
||||
assertEquals(goog.result.Result.State.ERROR, result.getState());
|
||||
|
||||
var error = result.getError();
|
||||
assertTrue(error instanceof goog.result.Result.CancelError);
|
||||
}
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,260 @@
|
||||
// Copyright 2012 The Closure Library Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS-IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/**
|
||||
* @fileoverview A SimpleResult object that implements goog.result.Result.
|
||||
* See below for a more detailed description.
|
||||
*/
|
||||
|
||||
goog.provide('goog.result.SimpleResult');
|
||||
goog.provide('goog.result.SimpleResult.StateError');
|
||||
|
||||
goog.require('goog.Promise');
|
||||
goog.require('goog.Thenable');
|
||||
goog.require('goog.debug.Error');
|
||||
goog.require('goog.result.Result');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A SimpleResult object is a basic implementation of the
|
||||
* goog.result.Result interface. This could be subclassed(e.g. XHRResult)
|
||||
* or instantiated and returned by another class as a form of result. The caller
|
||||
* receiving the result could then attach handlers to be called when the result
|
||||
* is resolved(success or error).
|
||||
*
|
||||
* @constructor
|
||||
* @implements {goog.result.Result}
|
||||
* @deprecated Use {@link goog.Promise} instead - http://go/promisemigration
|
||||
*/
|
||||
goog.result.SimpleResult = function() {
|
||||
/**
|
||||
* The current state of this Result.
|
||||
* @type {goog.result.Result.State}
|
||||
* @private
|
||||
*/
|
||||
this.state_ = goog.result.Result.State.PENDING;
|
||||
|
||||
/**
|
||||
* The list of handlers to call when this Result is resolved.
|
||||
* @type {!Array<!goog.result.SimpleResult.HandlerEntry_>}
|
||||
* @private
|
||||
*/
|
||||
this.handlers_ = [];
|
||||
|
||||
// The value_ and error_ properties are initialized in the constructor to
|
||||
// ensure that all SimpleResult instances share the same hidden class in
|
||||
// modern JavaScript engines.
|
||||
|
||||
/**
|
||||
* The 'value' of this Result.
|
||||
* @type {*}
|
||||
* @private
|
||||
*/
|
||||
this.value_ = undefined;
|
||||
|
||||
/**
|
||||
* The error slug for this Result.
|
||||
* @type {*}
|
||||
* @private
|
||||
*/
|
||||
this.error_ = undefined;
|
||||
};
|
||||
goog.Thenable.addImplementation(goog.result.SimpleResult);
|
||||
|
||||
|
||||
/**
|
||||
* A waiting handler entry.
|
||||
* @typedef {{
|
||||
* callback: !function(goog.result.SimpleResult),
|
||||
* scope: Object
|
||||
* }}
|
||||
* @private
|
||||
*/
|
||||
goog.result.SimpleResult.HandlerEntry_;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Error thrown if there is an attempt to set the value or error for this result
|
||||
* more than once.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {goog.debug.Error}
|
||||
* @final
|
||||
* @deprecated Use {@link goog.Promise} instead - http://go/promisemigration
|
||||
*/
|
||||
goog.result.SimpleResult.StateError = function() {
|
||||
goog.result.SimpleResult.StateError.base(this, 'constructor',
|
||||
'Multiple attempts to set the state of this Result');
|
||||
};
|
||||
goog.inherits(goog.result.SimpleResult.StateError, goog.debug.Error);
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.result.SimpleResult.prototype.getState = function() {
|
||||
return this.state_;
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.result.SimpleResult.prototype.getValue = function() {
|
||||
return this.value_;
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.result.SimpleResult.prototype.getError = function() {
|
||||
return this.error_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Attaches handlers to be called when the value of this Result is available.
|
||||
*
|
||||
* @param {!function(this:T, !goog.result.SimpleResult)} handler The function
|
||||
* called when the value is available. The function is passed the Result
|
||||
* object as the only argument.
|
||||
* @param {T=} opt_scope Optional scope for the handler.
|
||||
* @template T
|
||||
* @override
|
||||
*/
|
||||
goog.result.SimpleResult.prototype.wait = function(handler, opt_scope) {
|
||||
if (this.isPending_()) {
|
||||
this.handlers_.push({
|
||||
callback: handler,
|
||||
scope: opt_scope || null
|
||||
});
|
||||
} else {
|
||||
handler.call(opt_scope, this);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets the value of this Result, changing the state.
|
||||
*
|
||||
* @param {*} value The value to set for this Result.
|
||||
*/
|
||||
goog.result.SimpleResult.prototype.setValue = function(value) {
|
||||
if (this.isPending_()) {
|
||||
this.value_ = value;
|
||||
this.state_ = goog.result.Result.State.SUCCESS;
|
||||
this.callHandlers_();
|
||||
} else if (!this.isCanceled()) {
|
||||
// setValue is a no-op if this Result has been canceled.
|
||||
throw new goog.result.SimpleResult.StateError();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets the Result to be an error Result.
|
||||
*
|
||||
* @param {*=} opt_error Optional error slug to set for this Result.
|
||||
*/
|
||||
goog.result.SimpleResult.prototype.setError = function(opt_error) {
|
||||
if (this.isPending_()) {
|
||||
this.error_ = opt_error;
|
||||
this.state_ = goog.result.Result.State.ERROR;
|
||||
this.callHandlers_();
|
||||
} else if (!this.isCanceled()) {
|
||||
// setError is a no-op if this Result has been canceled.
|
||||
throw new goog.result.SimpleResult.StateError();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Calls the handlers registered for this Result.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
goog.result.SimpleResult.prototype.callHandlers_ = function() {
|
||||
var handlers = this.handlers_;
|
||||
this.handlers_ = [];
|
||||
for (var n = 0; n < handlers.length; n++) {
|
||||
var handlerEntry = handlers[n];
|
||||
handlerEntry.callback.call(handlerEntry.scope, this);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {boolean} Whether the Result is pending.
|
||||
* @private
|
||||
*/
|
||||
goog.result.SimpleResult.prototype.isPending_ = function() {
|
||||
return this.state_ == goog.result.Result.State.PENDING;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Cancels the Result.
|
||||
*
|
||||
* @return {boolean} Whether the result was canceled. It will not be canceled if
|
||||
* the result was already canceled or has already resolved.
|
||||
* @override
|
||||
*/
|
||||
goog.result.SimpleResult.prototype.cancel = function() {
|
||||
// cancel is a no-op if the result has been resolved.
|
||||
if (this.isPending_()) {
|
||||
this.setError(new goog.result.Result.CancelError());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.result.SimpleResult.prototype.isCanceled = function() {
|
||||
return this.state_ == goog.result.Result.State.ERROR &&
|
||||
this.error_ instanceof goog.result.Result.CancelError;
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.result.SimpleResult.prototype.then = function(
|
||||
opt_onFulfilled, opt_onRejected, opt_context) {
|
||||
var resolve, reject;
|
||||
// Copy the resolvers to outer scope, so that they are available
|
||||
// when the callback to wait() fires (which may be synchronous).
|
||||
var promise = new goog.Promise(function(res, rej) {
|
||||
resolve = res;
|
||||
reject = rej;
|
||||
});
|
||||
this.wait(function(result) {
|
||||
if (result.isCanceled()) {
|
||||
promise.cancel();
|
||||
} else if (result.getState() == goog.result.Result.State.SUCCESS) {
|
||||
resolve(result.getValue());
|
||||
} else if (result.getState() == goog.result.Result.State.ERROR) {
|
||||
reject(result.getError());
|
||||
}
|
||||
});
|
||||
return promise.then(opt_onFulfilled, opt_onRejected, opt_context);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates a SimpleResult that fires when the given promise resolves.
|
||||
* Use only during migration to Promises.
|
||||
* @param {!goog.Promise<?>} promise
|
||||
* @return {!goog.result.Result}
|
||||
*/
|
||||
goog.result.SimpleResult.fromPromise = function(promise) {
|
||||
var result = new goog.result.SimpleResult();
|
||||
promise.then(result.setValue, result.setError, result);
|
||||
return result;
|
||||
};
|
||||
@@ -0,0 +1,375 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!--
|
||||
Copyright 2012 The Closure Library Authors. All Rights Reserved.
|
||||
|
||||
Use of this source code is governed by the Apache License, Version 2.0.
|
||||
See the COPYING file for details.
|
||||
-->
|
||||
<head>
|
||||
<title>Closure Unit Tests - goog.result.SimpleResult</title>
|
||||
<script src="../base.js"></script>
|
||||
<script>
|
||||
|
||||
goog.require('goog.Timer');
|
||||
goog.require('goog.Promise');
|
||||
goog.require('goog.Thenable');
|
||||
goog.require('goog.result');
|
||||
goog.require('goog.testing.MockClock');
|
||||
goog.require('goog.testing.recordFunction');
|
||||
goog.require('goog.testing.jsunit');
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
|
||||
var result, mockClock, resultCallback;
|
||||
|
||||
function setUpPage() {
|
||||
mockClock = new goog.testing.MockClock();
|
||||
mockClock.install();
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
mockClock.reset();
|
||||
resultCallback = new goog.testing.recordFunction();
|
||||
resultCallback1 = new goog.testing.recordFunction();
|
||||
resultCallback2 = new goog.testing.recordFunction();
|
||||
result = new goog.result.SimpleResult();
|
||||
}
|
||||
|
||||
function tearDown() {
|
||||
resultCallback = resultCallback1 = resultCallback2 = result = null;
|
||||
}
|
||||
|
||||
function tearDownPage() {
|
||||
mockClock.uninstall();
|
||||
goog.dispose(mockClock);
|
||||
}
|
||||
|
||||
function testHandlersCalledOnSuccess() {
|
||||
result.wait(resultCallback1);
|
||||
result.wait(resultCallback2);
|
||||
|
||||
assertEquals(goog.result.Result.State.PENDING, result.getState());
|
||||
assertEquals(0, resultCallback1.getCallCount());
|
||||
assertEquals(0, resultCallback2.getCallCount());
|
||||
|
||||
result.setValue(2);
|
||||
|
||||
assertEquals(goog.result.Result.State.SUCCESS, result.getState());
|
||||
assertEquals(2, result.getValue());
|
||||
assertEquals(1, resultCallback1.getCallCount());
|
||||
assertEquals(1, resultCallback2.getCallCount());
|
||||
|
||||
var res1 = resultCallback1.popLastCall().getArgument(0);
|
||||
assertObjectEquals(result, res1);
|
||||
|
||||
var res2 = resultCallback2.popLastCall().getArgument(0);
|
||||
assertObjectEquals(result, res2);
|
||||
}
|
||||
|
||||
function testCustomHandlerScope() {
|
||||
result.wait(resultCallback1);
|
||||
var scope = {};
|
||||
result.wait(resultCallback2, scope);
|
||||
|
||||
result.setValue(2);
|
||||
|
||||
assertEquals(1, resultCallback1.getCallCount());
|
||||
assertEquals(1, resultCallback2.getCallCount());
|
||||
|
||||
var this1 = resultCallback1.popLastCall().getThis();
|
||||
assertObjectEquals(goog.global, this1);
|
||||
|
||||
var this2 = resultCallback2.popLastCall().getThis();
|
||||
assertObjectEquals(scope, this2);
|
||||
}
|
||||
|
||||
function testHandlersCalledOnError() {
|
||||
result.wait(resultCallback1);
|
||||
result.wait(resultCallback2);
|
||||
assertEquals(goog.result.Result.State.PENDING, result.getState());
|
||||
|
||||
var error = "Network Error";
|
||||
result.setError(error);
|
||||
|
||||
assertEquals(goog.result.Result.State.ERROR, result.getState());
|
||||
assertEquals(error, result.getError());
|
||||
assertEquals(1, resultCallback1.getCallCount());
|
||||
assertEquals(1, resultCallback2.getCallCount());
|
||||
|
||||
var res1 = resultCallback1.popLastCall().getArgument(0);
|
||||
assertObjectEquals(result, res1);
|
||||
var res2 = resultCallback2.popLastCall().getArgument(0);
|
||||
assertObjectEquals(result, res2);
|
||||
}
|
||||
|
||||
function testAttachingHandlerOnSuccessfulResult() {
|
||||
result.setValue(2);
|
||||
assertEquals(goog.result.Result.State.SUCCESS, result.getState());
|
||||
assertEquals(2, result.getValue());
|
||||
// resultCallback should be called immediately on a resolved Result
|
||||
assertEquals(0, resultCallback.getCallCount());
|
||||
|
||||
result.wait(resultCallback);
|
||||
|
||||
assertEquals(1, resultCallback.getCallCount());
|
||||
var res = resultCallback.popLastCall().getArgument(0);
|
||||
assertEquals(result, res);
|
||||
}
|
||||
|
||||
function testAttachingHandlerOnErrorResult() {
|
||||
var error = { code: -1, errorString: "Invalid JSON" };
|
||||
result.setError(error);
|
||||
assertEquals(goog.result.Result.State.ERROR, result.getState());
|
||||
assertEquals(error, result.getError());
|
||||
// resultCallback should be called immediately on a resolved Result
|
||||
assertEquals(0, resultCallback.getCallCount());
|
||||
|
||||
result.wait(resultCallback);
|
||||
|
||||
assertEquals(1, resultCallback.getCallCount());
|
||||
var res = resultCallback.popLastCall().getArgument(0);
|
||||
assertEquals(result, res);
|
||||
}
|
||||
|
||||
function testExceptionThrownOnMultipleSuccessfulResolutionAttempts() {
|
||||
result.setValue(1);
|
||||
assertEquals(goog.result.Result.State.SUCCESS, result.getState());
|
||||
assertEquals(1, result.getValue());
|
||||
|
||||
// Try to set the value again
|
||||
var e = assertThrows(goog.bind(result.setValue, result, 3));
|
||||
assertTrue(e instanceof goog.result.SimpleResult.StateError);
|
||||
}
|
||||
|
||||
function testExceptionThrownOnMultipleErrorResolutionAttempts() {
|
||||
assertEquals(goog.result.Result.State.PENDING, result.getState());
|
||||
|
||||
result.setError(5);
|
||||
|
||||
assertEquals(goog.result.Result.State.ERROR, result.getState());
|
||||
assertEquals(5, result.getError());
|
||||
// Try to set error again
|
||||
var e = assertThrows(goog.bind(result.setError, result, 4));
|
||||
assertTrue(e instanceof goog.result.SimpleResult.StateError);
|
||||
}
|
||||
|
||||
function testExceptionThrownOnSuccessThenErrorResolutionAttempt() {
|
||||
assertEquals(goog.result.Result.State.PENDING, result.getState());
|
||||
|
||||
result.setValue(1);
|
||||
|
||||
assertEquals(goog.result.Result.State.SUCCESS, result.getState());
|
||||
assertEquals(1, result.getValue());
|
||||
|
||||
// Try to set error after setting value
|
||||
var e = assertThrows(goog.bind(result.setError, result, 3));
|
||||
assertTrue(e instanceof goog.result.SimpleResult.StateError);
|
||||
}
|
||||
|
||||
function testExceptionThrownOnErrorThenSuccessResolutionAttempt() {
|
||||
assertEquals(goog.result.Result.State.PENDING, result.getState());
|
||||
|
||||
var error = "fail";
|
||||
result.setError(error);
|
||||
|
||||
assertEquals(goog.result.Result.State.ERROR, result.getState());
|
||||
assertEquals(error, result.getError());
|
||||
// Try to set value after setting error
|
||||
var e = assertThrows(goog.bind(result.setValue, result, 1));
|
||||
assertTrue(e instanceof goog.result.SimpleResult.StateError);
|
||||
}
|
||||
|
||||
function testSuccessfulAsyncResolution() {
|
||||
result.wait(resultCallback);
|
||||
assertEquals(goog.result.Result.State.PENDING, result.getState());
|
||||
|
||||
goog.Timer.callOnce(function() {
|
||||
result.setValue(1);
|
||||
});
|
||||
mockClock.tick();
|
||||
|
||||
assertEquals(1, resultCallback.getCallCount());
|
||||
|
||||
var res = resultCallback.popLastCall().getArgument(0);
|
||||
assertEquals(goog.result.Result.State.SUCCESS, res.getState());
|
||||
assertEquals(1, res.getValue());
|
||||
}
|
||||
|
||||
function testErrorAsyncResolution() {
|
||||
result.wait(resultCallback);
|
||||
assertEquals(goog.result.Result.State.PENDING, result.getState());
|
||||
|
||||
var error = 'Network failure';
|
||||
goog.Timer.callOnce(function() {
|
||||
result.setError(error);
|
||||
});
|
||||
mockClock.tick();
|
||||
|
||||
assertEquals(1, resultCallback.getCallCount());
|
||||
var res = resultCallback.popLastCall().getArgument(0);
|
||||
assertEquals(goog.result.Result.State.ERROR, res.getState());
|
||||
assertEquals(error, res.getError());
|
||||
}
|
||||
|
||||
function testCancelStateAndReturn() {
|
||||
assertFalse(result.isCanceled());
|
||||
var canceled = result.cancel();
|
||||
assertTrue(result.isCanceled());
|
||||
assertEquals(goog.result.Result.State.ERROR, result.getState());
|
||||
assertTrue(result.getError() instanceof goog.result.Result.CancelError);
|
||||
assertTrue(canceled);
|
||||
}
|
||||
|
||||
function testErrorHandlersFireOnCancel() {
|
||||
result.wait(resultCallback);
|
||||
result.cancel();
|
||||
|
||||
assertEquals(1, resultCallback.getCallCount());
|
||||
var lastCall = resultCallback.popLastCall();
|
||||
var res = lastCall.getArgument(0);
|
||||
assertEquals(goog.result.Result.State.ERROR, res.getState());
|
||||
assertTrue(res.getError() instanceof goog.result.Result.CancelError);
|
||||
}
|
||||
|
||||
function testCancelAfterSetValue() {
|
||||
// cancel after setValue/setError => no-op
|
||||
result.wait(resultCallback);
|
||||
result.setValue(1);
|
||||
|
||||
assertEquals(goog.result.Result.State.SUCCESS, result.getState());
|
||||
assertEquals(1, result.getValue());
|
||||
assertEquals(1, resultCallback.getCallCount());
|
||||
|
||||
result.cancel();
|
||||
|
||||
assertEquals(goog.result.Result.State.SUCCESS, result.getState());
|
||||
assertEquals(1, result.getValue());
|
||||
assertEquals(1, resultCallback.getCallCount());
|
||||
}
|
||||
|
||||
function testSetValueAfterCancel() {
|
||||
// setValue/setError after cancel => no-op
|
||||
result.wait(resultCallback);
|
||||
|
||||
result.cancel();
|
||||
assertTrue(result.isCanceled());
|
||||
assertTrue(result.getError() instanceof goog.result.Result.CancelError);
|
||||
|
||||
result.setValue(1);
|
||||
assertTrue(result.isCanceled());
|
||||
assertTrue(result.getError() instanceof goog.result.Result.CancelError);
|
||||
|
||||
result.setError(3);
|
||||
assertTrue(result.isCanceled());
|
||||
assertTrue(result.getError() instanceof goog.result.Result.CancelError);
|
||||
}
|
||||
|
||||
function testFromResolvedPromise() {
|
||||
var promise = goog.Promise.resolve('resolved');
|
||||
result = goog.result.SimpleResult.fromPromise(promise);
|
||||
assertEquals(goog.result.Result.State.PENDING, result.getState());
|
||||
mockClock.tick();
|
||||
assertEquals(goog.result.Result.State.SUCCESS, result.getState());
|
||||
assertEquals('resolved', result.getValue());
|
||||
assertEquals(undefined, result.getError());
|
||||
}
|
||||
|
||||
function testFromRejectedPromise() {
|
||||
var promise = goog.Promise.reject('rejected');
|
||||
result = goog.result.SimpleResult.fromPromise(promise);
|
||||
assertEquals(goog.result.Result.State.PENDING, result.getState());
|
||||
mockClock.tick();
|
||||
assertEquals(goog.result.Result.State.ERROR, result.getState());
|
||||
assertEquals(undefined, result.getValue());
|
||||
assertEquals('rejected', result.getError());
|
||||
}
|
||||
|
||||
function testThen() {
|
||||
var value1, value2;
|
||||
result.then(function(val1) {
|
||||
return value1 = val1;
|
||||
}).then(function(val2) {
|
||||
value2 = val2;
|
||||
});
|
||||
result.setValue('done');
|
||||
assertUndefined(value1);
|
||||
assertUndefined(value2);
|
||||
mockClock.tick();
|
||||
assertEquals('done', value1);
|
||||
assertEquals('done', value2);
|
||||
}
|
||||
|
||||
function testThen_reject() {
|
||||
var value, reason;
|
||||
result.then(
|
||||
function(v) { value = v; },
|
||||
function(r) { reason = r; });
|
||||
result.setError(new Error('oops'));
|
||||
assertUndefined(value);
|
||||
mockClock.tick();
|
||||
assertUndefined(value);
|
||||
assertEquals('oops', reason.message);
|
||||
}
|
||||
|
||||
function testPromiseAll() {
|
||||
var promise = goog.Promise.resolve('promise');
|
||||
goog.Promise.all([result, promise]).then(function(values) {
|
||||
assertEquals(2, values.length);
|
||||
assertEquals('result', values[0]);
|
||||
assertEquals('promise', values[1]);
|
||||
});
|
||||
result.setValue('result');
|
||||
mockClock.tick();
|
||||
}
|
||||
|
||||
function testResolvingPromiseBlocksResult() {
|
||||
var value;
|
||||
goog.Promise.resolve('promise').then(function(value) {
|
||||
result.setValue(value);
|
||||
});
|
||||
result.wait(function(r) {
|
||||
value = r.getValue();
|
||||
});
|
||||
assertUndefined(value);
|
||||
mockClock.tick();
|
||||
assertEquals('promise', value);
|
||||
}
|
||||
|
||||
function testRejectingPromiseBlocksResult() {
|
||||
var err;
|
||||
goog.Promise.reject(new Error('oops')).then(
|
||||
undefined /* opt_onResolved */,
|
||||
function(reason) {
|
||||
result.setError(reason);
|
||||
});
|
||||
result.wait(function(r) {
|
||||
err = r.getError();
|
||||
});
|
||||
assertUndefined(err);
|
||||
mockClock.tick();
|
||||
assertEquals('oops', err.message);
|
||||
}
|
||||
|
||||
function testPromiseFromCanceledResult() {
|
||||
var reason;
|
||||
result.cancel();
|
||||
result.then(
|
||||
undefined /* opt_onResolved */,
|
||||
function(r) {
|
||||
reason = r;
|
||||
});
|
||||
mockClock.tick();
|
||||
assertTrue(reason instanceof goog.Promise.CancellationError);
|
||||
}
|
||||
|
||||
function testThenableInterface() {
|
||||
assertTrue(goog.Thenable.isImplementedBy(result));
|
||||
}
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,153 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!--
|
||||
Copyright 2012 The Closure Library Authors. All Rights Reserved.
|
||||
|
||||
Use of this source code is governed by the Apache License, Version 2.0.
|
||||
See the COPYING file for details.
|
||||
-->
|
||||
<head>
|
||||
<title>Closure Unit Tests - goog.result.transform</title>
|
||||
<script src="../base.js"></script>
|
||||
<script>
|
||||
|
||||
goog.require('goog.Timer');
|
||||
goog.require('goog.result.SimpleResult');
|
||||
goog.require('goog.result');
|
||||
goog.require('goog.testing.MockClock');
|
||||
goog.require('goog.testing.jsunit');
|
||||
goog.require('goog.testing.recordFunction');
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
|
||||
var result, resultCallback, multiplyResult, mockClock;
|
||||
|
||||
function setUpPage() {
|
||||
mockClock = new goog.testing.MockClock();
|
||||
mockClock.install();
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
mockClock.reset();
|
||||
result = new goog.result.SimpleResult();
|
||||
resultCallback = new goog.testing.recordFunction();
|
||||
multiplyResult = goog.testing.recordFunction(function(value) {
|
||||
return value * 2;
|
||||
});
|
||||
}
|
||||
|
||||
function tearDown() {
|
||||
result = multiplyResult = null;
|
||||
}
|
||||
|
||||
function tearDownPage() {
|
||||
mockClock.uninstall();
|
||||
goog.dispose(mockClock);
|
||||
}
|
||||
|
||||
function testTransformWhenResultSuccess() {
|
||||
var transformedResult = goog.result.transform(result, multiplyResult);
|
||||
goog.result.wait(transformedResult, resultCallback);
|
||||
|
||||
assertEquals(goog.result.Result.State.PENDING, result.getState());
|
||||
result.setValue(1);
|
||||
assertTransformerCall(multiplyResult, 1);
|
||||
assertSuccessCall(resultCallback, transformedResult, 2);
|
||||
}
|
||||
|
||||
function testTransformWhenResultSuccessAsync() {
|
||||
var transformedResult = goog.result.transform(result, multiplyResult);
|
||||
goog.result.wait(transformedResult, resultCallback);
|
||||
|
||||
goog.Timer.callOnce(function() {
|
||||
result.setValue(1);
|
||||
});
|
||||
|
||||
assertEquals(goog.result.Result.State.PENDING, result.getState());
|
||||
mockClock.tick();
|
||||
assertTransformerCall(multiplyResult, 1);
|
||||
assertSuccessCall(resultCallback, transformedResult, 2);
|
||||
}
|
||||
|
||||
function testTransformWhenResultError() {
|
||||
var transformedResult = goog.result.transform(result, multiplyResult);
|
||||
goog.result.wait(transformedResult, resultCallback);
|
||||
|
||||
assertEquals(goog.result.Result.State.PENDING, result.getState());
|
||||
result.setError(4);
|
||||
assertNoCall(multiplyResult);
|
||||
assertErrorCall(resultCallback, transformedResult, 4);
|
||||
}
|
||||
|
||||
function testTransformWhenResultErrorAsync() {
|
||||
var transformedResult = goog.result.transform(result, multiplyResult);
|
||||
|
||||
goog.result.wait(transformedResult, resultCallback);
|
||||
|
||||
goog.Timer.callOnce(function() {
|
||||
result.setError(5);
|
||||
});
|
||||
|
||||
assertEquals(goog.result.Result.State.PENDING, result.getState());
|
||||
mockClock.tick();
|
||||
assertNoCall(multiplyResult);
|
||||
assertErrorCall(resultCallback, transformedResult, 5);
|
||||
}
|
||||
|
||||
function testCancelParentResults() {
|
||||
var transformedResult = goog.result.transform(result, multiplyResult);
|
||||
goog.result.wait(transformedResult, resultCallback);
|
||||
|
||||
goog.result.cancelParentResults(transformedResult);
|
||||
|
||||
assertTrue(result.isCanceled());
|
||||
result.setValue(1);
|
||||
assertNoCall(multiplyResult);
|
||||
}
|
||||
|
||||
function testDoubleTransformCancel() {
|
||||
var step1Result = goog.result.transform(result, multiplyResult);
|
||||
var step2Result = goog.result.transform(step1Result, multiplyResult);
|
||||
|
||||
goog.result.cancelParentResults(step2Result);
|
||||
|
||||
assertFalse(result.isCanceled());
|
||||
assertTrue(step1Result.isCanceled());
|
||||
assertTrue(step2Result.isCanceled());
|
||||
}
|
||||
|
||||
function assertSuccessCall(recordFunction, result, value) {
|
||||
assertEquals(1, recordFunction.getCallCount());
|
||||
|
||||
var res = recordFunction.popLastCall().getArgument(0);
|
||||
assertEquals(result, res);
|
||||
assertEquals(goog.result.Result.State.SUCCESS, res.getState());
|
||||
assertEquals(value, res.getValue());
|
||||
}
|
||||
|
||||
function assertErrorCall(recordFunction, result, value) {
|
||||
assertEquals(1, recordFunction.getCallCount());
|
||||
|
||||
var res = recordFunction.popLastCall().getArgument(0);
|
||||
assertEquals(result, res);
|
||||
assertEquals(goog.result.Result.State.ERROR, res.getState());
|
||||
assertEquals(value, res.getError());
|
||||
}
|
||||
|
||||
function assertNoCall(recordFunction) {
|
||||
assertEquals(0, recordFunction.getCallCount());
|
||||
}
|
||||
|
||||
function assertTransformerCall(recordFunction, value) {
|
||||
assertEquals(1, recordFunction.getCallCount());
|
||||
|
||||
var argValue = recordFunction.popLastCall().getArgument(0);
|
||||
assertEquals(value, argValue);
|
||||
}
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,211 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!--
|
||||
Copyright 2012 The Closure Library Authors. All Rights Reserved.
|
||||
|
||||
Use of this source code is governed by the Apache License, Version 2.0.
|
||||
See the COPYING file for details.
|
||||
-->
|
||||
<head>
|
||||
<title>Closure Unit Tests - goog.result.wait</title>
|
||||
<script src="../base.js"></script>
|
||||
<script>
|
||||
|
||||
goog.require('goog.Timer');
|
||||
goog.require('goog.result.SimpleResult');
|
||||
goog.require('goog.result');
|
||||
goog.require('goog.testing.MockClock');
|
||||
goog.require('goog.testing.jsunit');
|
||||
goog.require('goog.testing.recordFunction');
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
|
||||
var result, waitCallback, waitOnSuccessCallback, waitOnErrorCallback;
|
||||
|
||||
var mockClock, propertyReplacer;
|
||||
|
||||
function setUpPage() {
|
||||
mockClock = new goog.testing.MockClock();
|
||||
mockClock.install();
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
mockClock.reset();
|
||||
result = new goog.result.SimpleResult();
|
||||
propertyReplacer = new goog.testing.PropertyReplacer();
|
||||
waitCallback = new goog.testing.recordFunction();
|
||||
waitOnSuccessCallback = new goog.testing.recordFunction();
|
||||
waitOnErrorCallback = new goog.testing.recordFunction();
|
||||
}
|
||||
|
||||
function tearDown() {
|
||||
result = waitCallback = waitOnSuccessCallback = waitOnErrorCallback = null;
|
||||
propertyReplacer.reset();
|
||||
}
|
||||
|
||||
function tearDownPage() {
|
||||
mockClock.uninstall();
|
||||
}
|
||||
|
||||
function testSynchronousSuccess() {
|
||||
assertEquals(goog.result.Result.State.PENDING, result.getState());
|
||||
assertUndefined(result.getValue());
|
||||
|
||||
goog.result.wait(result, waitCallback);
|
||||
goog.result.waitOnSuccess(result, waitOnSuccessCallback);
|
||||
goog.result.waitOnError(result, waitOnErrorCallback);
|
||||
|
||||
result.setValue(1);
|
||||
|
||||
assertEquals(goog.result.Result.State.SUCCESS, result.getState());
|
||||
assertEquals(1, result.getValue());
|
||||
|
||||
assertWaitCall(waitCallback, result);
|
||||
assertCall(waitOnSuccessCallback, 1, result);
|
||||
assertNoCall(waitOnErrorCallback);
|
||||
}
|
||||
|
||||
function testAsynchronousSuccess() {
|
||||
goog.result.wait(result, waitCallback);
|
||||
goog.result.waitOnSuccess(result, waitOnSuccessCallback);
|
||||
goog.result.waitOnError(result, waitOnErrorCallback);
|
||||
|
||||
goog.Timer.callOnce(function() {
|
||||
result.setValue(1);
|
||||
});
|
||||
|
||||
assertUndefined(result.getValue());
|
||||
assertEquals(goog.result.Result.State.PENDING, result.getState());
|
||||
|
||||
assertNoCall(waitCallback);
|
||||
assertNoCall(waitOnSuccessCallback);
|
||||
assertNoCall(waitOnErrorCallback);
|
||||
|
||||
mockClock.tick();
|
||||
|
||||
assertEquals(goog.result.Result.State.SUCCESS, result.getState());
|
||||
assertEquals(1, result.getValue());
|
||||
|
||||
assertWaitCall(waitCallback, result);
|
||||
assertCall(waitOnSuccessCallback, 1, result);
|
||||
assertNoCall(waitOnErrorCallback);
|
||||
}
|
||||
|
||||
function testSynchronousError() {
|
||||
assertEquals(goog.result.Result.State.PENDING, result.getState());
|
||||
assertUndefined(result.getValue());
|
||||
|
||||
goog.result.wait(result, waitCallback);
|
||||
goog.result.waitOnSuccess(result, waitOnSuccessCallback);
|
||||
goog.result.waitOnError(result, waitOnErrorCallback);
|
||||
|
||||
result.setError();
|
||||
|
||||
assertEquals(goog.result.Result.State.ERROR, result.getState());
|
||||
assertUndefined(result.getValue());
|
||||
|
||||
assertWaitCall(waitCallback, result);
|
||||
assertNoCall(waitOnSuccessCallback);
|
||||
assertCall(waitOnErrorCallback, undefined, result);
|
||||
}
|
||||
|
||||
function testAsynchronousError() {
|
||||
goog.result.wait(result, waitCallback);
|
||||
goog.result.waitOnSuccess(result, waitOnSuccessCallback);
|
||||
goog.result.waitOnError(result, waitOnErrorCallback);
|
||||
|
||||
goog.Timer.callOnce(function() {
|
||||
result.setError();
|
||||
});
|
||||
|
||||
assertEquals(goog.result.Result.State.PENDING, result.getState());
|
||||
assertUndefined(result.getValue());
|
||||
|
||||
assertNoCall(waitCallback);
|
||||
assertNoCall(waitOnSuccessCallback);
|
||||
assertNoCall(waitOnErrorCallback);
|
||||
|
||||
mockClock.tick();
|
||||
|
||||
assertEquals(goog.result.Result.State.ERROR, result.getState());
|
||||
assertUndefined(result.getValue());
|
||||
|
||||
assertWaitCall(waitCallback, result);
|
||||
assertNoCall(waitOnSuccessCallback);
|
||||
assertCall(waitOnErrorCallback, undefined, result);
|
||||
}
|
||||
|
||||
function testCustomScope() {
|
||||
var scope = {};
|
||||
goog.result.wait(result, waitCallback, scope);
|
||||
result.setValue(1);
|
||||
assertEquals(scope, waitCallback.popLastCall().getThis());
|
||||
}
|
||||
|
||||
function testDefaultScope() {
|
||||
goog.result.wait(result, waitCallback);
|
||||
result.setValue(1);
|
||||
assertEquals(goog.global, waitCallback.popLastCall().getThis());
|
||||
}
|
||||
|
||||
function testOnSuccessScope() {
|
||||
var scope = {};
|
||||
goog.result.waitOnSuccess(result, waitOnSuccessCallback, scope);
|
||||
result.setValue(1);
|
||||
assertCall(waitOnSuccessCallback, 1, result, scope);
|
||||
}
|
||||
|
||||
function testOnErrorScope() {
|
||||
var scope = {};
|
||||
goog.result.waitOnError(result, waitOnErrorCallback, scope);
|
||||
result.setError();
|
||||
assertCall(waitOnErrorCallback, undefined, result, scope);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that a callback function stubbed out with goog.recordFunction was
|
||||
* called with the expected arguments by goog.result.waitOnSuccess/Error.
|
||||
* @param {Function} recordedFunction The callback function.
|
||||
* @param {?} value The value stored in the result.
|
||||
* @param {!goog.result.Result} result The result that was resolved to SUCCESS
|
||||
* or ERROR.
|
||||
* @param {Object=} opt_scope Optional scope that the test function should be
|
||||
* called in. By default, it is goog.global.
|
||||
*/
|
||||
function assertCall(recordedFunction, value, result, opt_scope) {
|
||||
var scope = opt_scope || goog.global;
|
||||
assertEquals(1, recordedFunction.getCallCount());
|
||||
var call = recordedFunction.popLastCall();
|
||||
assertEquals(2, call.getArguments().length);
|
||||
assertEquals(value, call.getArgument(0));
|
||||
assertEquals(result, call.getArgument(1));
|
||||
assertEquals(scope, call.getThis());
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that a callback function stubbed out with goog.recordFunction was
|
||||
* called with the expected arguments by goog.result.wait.
|
||||
* @param {Function} recordedFunction The callback function.
|
||||
* @param {!goog.result.Result} result The result that was resolved to SUCCESS
|
||||
* or ERROR.
|
||||
* @param {Object=} opt_scope Optional scope that the test function should be
|
||||
* called in. By default, it is goog.global.
|
||||
*/
|
||||
function assertWaitCall(recordedFunction, result, opt_scope) {
|
||||
var scope = opt_scope || goog.global;
|
||||
assertEquals(1, recordedFunction.getCallCount());
|
||||
var call = recordedFunction.popLastCall();
|
||||
assertEquals(1, call.getArguments().length);
|
||||
assertEquals(result, call.getArgument(0));
|
||||
assertEquals(scope, call.getThis());
|
||||
}
|
||||
|
||||
function assertNoCall(recordedFunction) {
|
||||
assertEquals(0, recordedFunction.getCallCount());
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user