Skip to content

Instantly share code, notes, and snippets.

@whitelynx
Forked from Morgul/promise-proxy.js
Last active August 29, 2015 14:11
Show Gist options
  • Save whitelynx/94b00aa5b995c0b46283 to your computer and use it in GitHub Desktop.
Save whitelynx/94b00aa5b995c0b46283 to your computer and use it in GitHub Desktop.
// ---------------------------------------------------------------------------------------------------------------------
// PromiseProxy - A proxy object that wraps a promise, and exposes `pending`, `result` and `error` properties. This is
// most useful when setting results of promises on the scope directly, so you can work with them in your templates.
//
// @module promise-proxy.js
// ---------------------------------------------------------------------------------------------------------------------
function PromiseProxyFactory(promise)
{
var proxy = {
pending: true,
promise: promise
};
promise.then(
function(result)
{
proxy.pending = false;
proxy.result = result;
},
function(error)
{
proxy.pending = false;
proxy.error = error;
});
return proxy;
} // end PromiseProxyFactory
// ---------------------------------------------------------------------------------------------------------------------
angular.module('promise-proxy', []).value('promise-proxy', PromiseProxyFactory);
// ---------------------------------------------------------------------------------------------------------------------
(function() {
var promiseProxyModule = angular.module('promise-proxy')
.directive('proxy', function()
{
return {
restrict: 'A',
transclude: true,
scope: { promise: '=proxy' },
controller: [
'$scope', '$element', '$transclude', 'promise-proxy',
function($scope, $element, $transclude, proxy)
{
var self = this;
this.state = {};
$scope.$watch('promise', function(promise)
{
if(promise !== undefined)
{
self.state = (promise.then) ? proxy(promise) : promise;
} // end if
});
$transclude(function(clone, transclusionScope)
{
$element.append(clone);
Object.defineProperties(transclusionScope, {
pending: { get: function() { return self.state.pending; } },
resolved: { get: function() { return Object.hasKey(self.state, 'result'); } },
result: { get: function() { return self.state.result; } },
error: { get: function() { return self.state.error; } }
});
});
}
]
};
});
makeInnerProxyDirective('pending');
makeInnerProxyDirective('result');
makeInnerProxyDirective('error');
function makeInnerProxyDirective(name)
{
promiseProxyModule.directive(name, function()
{
return {
require: '^^proxy',
restrict: 'E',
transclude: true,
scope: {},
link: function(scope, element, attrs, proxyCtrl)
{
Object.defineProperty(scope, 'visible', {
get: function() { return proxyCtrl.state[name]; }
});
},
template: '<span ng-if="visible" ng-transclude></span>'
};
});
} // end makeInnerProxyDirective
})();
<html ng-app="testApp">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.7/angular.min.js"></script>
<script src="promise-proxy.js"></script>
<script src="proxy-directive.js"></script>
<script>
angular.module('testApp', ['promise-proxy'])
.controller('TestCtrl', function($scope, $http, $timeout)
{
$scope.tests = [
$http.get('test.json')
.then(function(response) { return response.data; }),
$timeout(function()
{
return { first: "Boo", last: "Smith" };
}, 1000),
$timeout(function()
{
throw new Error("Something exploded!");
}, 2000),
];
});
</script>
</head>
<body ng-controller="TestCtrl">
<ol>
<li ng-repeat="testData in tests" proxy="testData">
<pending>
Loading...
</pending>
<result>
Hello, {{result.first}} {{result.last}}!
</result>
<error style="color: red;">
An error occured:
<pre>{{error.stack || error.message}}</pre>
</error>
</li>
</ol>
</body>
</html>
{"first":"Dudley","last":"Smith"}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment