{"id":2185,"date":"2022-08-30T15:22:45","date_gmt":"2022-08-30T15:22:45","guid":{"rendered":"https:\/\/unknownerror.org\/index.php\/2014\/01\/04\/angular-directive-correlative-requests-collection-of-common-programming-errors\/"},"modified":"2022-08-30T15:22:45","modified_gmt":"2022-08-30T15:22:45","slug":"angular-directive-correlative-requests-collection-of-common-programming-errors","status":"publish","type":"post","link":"https:\/\/unknownerror.org\/index.php\/2022\/08\/30\/angular-directive-correlative-requests-collection-of-common-programming-errors\/","title":{"rendered":"angular directive &#8211; correlative requests-Collection of common programming errors"},"content":{"rendered":"<p>I&#8217;ll float this Reverse-Jeopardy style (A question in the form of an answer). I&#8217;ve been mulling over a solution to this problem I saw recently. It clearly works, but it has some behavioral traits that I was first tempted to label as &#8220;wrong&#8221;. On deeper reflection, I realized that those traits may be desirable <strong>in some very specific scenarios<\/strong>.<\/p>\n<p>I would certainly not pitch this as a general solution to use each time you run into a need to bind data that is returned asynchronously. I present it to highlight the fact that the questions posed by this scenario have multiple potential answers. In some cases, there may be a genuine business logic need to block the UI rendering until the service call returns. In other cases, keeping the UI live and responsive for unrelated work may be more appropriate.<\/p>\n<p>For example, in the case of an order processing system, I might very well want to block the client thread from interacting with view elements until the result of a sales transaction was known. The same could not be said of something like a web-based spreadsheet application with server-side formula calculations.<\/p>\n<p>I think its a wonderful thing that both asynchronous and synchronous modes of addressing this need can co-exist. That is to say, returning a promise object does not obligate a client to use it any more than placing the return values in a scope obligates a client to watch them.<\/p>\n<p>What follows demonstrates a way of handling this requirement <em>synchronously<\/em> alongside the previously explored asynchronous <code>watch( )<\/code> style.:<\/p>\n<pre><code>var servicesModule = servicesModule || angular.module('myModule', []);\n\nservicesModule.factory('thingClient', \n    ['$http', '$q', function( $http, $q ) {\n        return new ThingClient($http, $q);\n    }]\n);\n\nfunction ThingClient($http, $q) {\n    function callService(scopeObject) {\n        var defer = $q.defer();\n        var promise = defer.promise;\n        $http({\n            method: 'POST',\n            url: 'http:\/\/at\/some\/url\/',\n            data: { x: 'y', y: 'z', z: 'x', one: 1, two: 2, three: 3},\n            cache: false\n        }, function(data) {\n            scopeObject.data = data;\n            defer.resolve(data);\n        }, function() {\n            scopeObject.data = null;\n            defer.resolve(null)\n        });\n\n        return promise;\n    }\n}\n<\/code><\/pre>\n<p>client-service.js<\/p>\n<pre><code>function ConsumingController( $scope, thingClient ) {\n    \/\/ Be careful to use an object (so you have data wrapped such that it\n    \/\/ is eligible for prototypical inheritance and call by reference without\n    \/\/ passing the scope itself).  Leave the 'data' element undefined so you\n    \/\/ can trigger the transition from undefined -&gt; null in the failure case\n    \/\/ and not just the on-success case. \n    $scope.dto = { data: undefined };\n    var promise = thingClient.callService(scope.dto);\n\n    \/\/ Asynchronous strategy\n    $scope.$watch('offer.myId', function (newValue, oldValue) {\n        if( newValue == null ) {\n            \/\/ Fail!\n        } else {\n            \/\/ Succeed!\n        }\n    }\n\n    \/\/ Synchronous strategy\n    if( promise.then( \n        function(data) { \n            if( data == null ) { \n                \/\/ Fail\n            } else {\n                \/\/ Succeed\n            }\n        }\n    }\n}\n<\/code><\/pre>\n<p>consuming-controller.js<\/p>\n<p id=\"rop\"><small>Originally posted 2014-01-04 02:52:16. <\/small><\/p>","protected":false},"excerpt":{"rendered":"<p>I&#8217;ll float this Reverse-Jeopardy style (A question in the form of an answer). I&#8217;ve been mulling over a solution to this problem I saw recently. It clearly works, but it has some behavioral traits that I was first tempted to label as &#8220;wrong&#8221;. On deeper reflection, I realized that those traits may be desirable in [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-2185","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts\/2185","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/comments?post=2185"}],"version-history":[{"count":0,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts\/2185\/revisions"}],"wp:attachment":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/media?parent=2185"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/categories?post=2185"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/tags?post=2185"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}