{"componentChunkName":"component---src-templates-generic-template-js","path":"/lectures/lecture7-rest","webpackCompilationHash":"041090671d318979d692","result":{"data":{"markdownRemark":{"htmlAst":{"type":"root","children":[{"type":"element","tagName":"h2","properties":{"id":"obtaining-application-state"},"children":[{"type":"element","tagName":"a","properties":{"href":"#obtaining-application-state","ariaLabel":"obtaining application state permalink","className":["anchor"]},"children":[{"type":"element","tagName":"svg","properties":{"ariaHidden":"true","focusable":"false","height":"16","version":"1.1","viewBox":"0 0 16 16","width":"16"},"children":[{"type":"element","tagName":"path","properties":{"fillRule":"evenodd","d":"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"},"children":[]}]}]},{"type":"text","value":"Obtaining application state"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"It is unusual to embed data directly in an application is we did in the initial\nversions of Simplepedia and the standalone Film Explorer. More typical is to\nfetch the data as needed from a server with an AJAX request (Asynchronous\nJavaScript and XML) and persist new or changed data by sending it back to the\nserver (also via AJAX). AJAX is a technique (with multiple underlying\nimplementations) to request data from a remote resource in the background\nwithout reloading the webpage."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h2","properties":{"id":"modifying-application-state"},"children":[{"type":"element","tagName":"a","properties":{"href":"#modifying-application-state","ariaLabel":"modifying application state permalink","className":["anchor"]},"children":[{"type":"element","tagName":"svg","properties":{"ariaHidden":"true","focusable":"false","height":"16","version":"1.1","viewBox":"0 0 16 16","width":"16"},"children":[{"type":"element","tagName":"path","properties":{"fillRule":"evenodd","d":"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"},"children":[]}]}]},{"type":"text","value":"Modifying application state"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"The next feature we want to add to the Film Explorer is the ability to add our\nown ratings, i.e."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"\"As a user, I want to rate the movies myself so that I can record and review my\nopinion of the movie\""}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"As we saw in class, FilmExplorer already supports this, but the data is\ncurrently ephemeral; if I restart the application, it is lost. If I want the\nrating to persist I will need store those updates somewhere - the server."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Implementing this kind of interaction motivates us to learn about client-server\narchitectures, HTTP, REST (and REST APIs)."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h2","properties":{"id":"client-server"},"children":[{"type":"element","tagName":"a","properties":{"href":"#client-server","ariaLabel":"client server permalink","className":["anchor"]},"children":[{"type":"element","tagName":"svg","properties":{"ariaHidden":"true","focusable":"false","height":"16","version":"1.1","viewBox":"0 0 16 16","width":"16"},"children":[{"type":"element","tagName":"path","properties":{"fillRule":"evenodd","d":"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"},"children":[]}]}]},{"type":"text","value":"Client-Server"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Web applications are "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"client-server"}]},{"type":"text","value":" (vs. peer-to-peer) and generally\n"},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"request-response"}]},{"type":"text","value":" (vs. push, although there are push technologies via\nWebSocket)."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Client-Server is a design pattern:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"ul","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"The client enables users to interact with data"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"The server waits for and respond to requests for many clients"}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h3","properties":{"id":"underlying-protocols"},"children":[{"type":"element","tagName":"a","properties":{"href":"#underlying-protocols","ariaLabel":"underlying protocols permalink","className":["anchor"]},"children":[{"type":"element","tagName":"svg","properties":{"ariaHidden":"true","focusable":"false","height":"16","version":"1.1","viewBox":"0 0 16 16","width":"16"},"children":[{"type":"element","tagName":"path","properties":{"fillRule":"evenodd","d":"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"},"children":[]}]}]},{"type":"text","value":"Underlying protocols"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Recall that TCP/IP provides an abstraction of a reliable stream between IP\nnodes (addressed by by four octets, e.g. 127.0.0.1). TCP ports enable multiple\napplications on the same node to use TCP/IP concurrently and independently.\nThese are logical not physical ports. Many protocols have specified\n\"well-known\" ports (e.g. 22 for SSH), enabling clients to make connections just\nknowing the IP address (doesn't mean those services are provided on every\nserver)."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Hypertext Transfer Protocol (HTTP) is a request-response protocol for the Web.\nAn HTTP request includes:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"ul","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"The request method (GET, POST, etc.)"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Uniform Resource Identifier (URI)"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"The HTTP protocol version understood by the client"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Headers (extra information about request, e.g. the kind of response\naccepted)"}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"While the HTTP response from server includes:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"ul","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Protocol version and status code (2** OK, 3** resource moved, 4**\nforbidden, etc., 5** error)"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Headers"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Body"}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"The HTTP methods or verbs are:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"ul","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"GET: Request a resource. Form fields can be sent as the query parameters."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"HEAD: Similar to GET, but just the response headers"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"POST: Send data to the server. Unlike GET, the data is transmitted in the\nrequest body rather than as part of the URL. What is done with the data is up\nto the server. The response may be a new resource, or just a status code."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"PUT: Similar to POST, expect that PUT is intended to create or modify the\nresource at the specified URL, while POST creates or updates a subordinate\nresource."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"DELETE: Delete the specified resource"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"PATCH: Partial replacement of a resource, as opposed to PUT which specifies\ncomplete replacement."}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h3","properties":{"id":"rest"},"children":[{"type":"element","tagName":"a","properties":{"href":"#rest","ariaLabel":"rest permalink","className":["anchor"]},"children":[{"type":"element","tagName":"svg","properties":{"ariaHidden":"true","focusable":"false","height":"16","version":"1.1","viewBox":"0 0 16 16","width":"16"},"children":[{"type":"element","tagName":"path","properties":{"fillRule":"evenodd","d":"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"},"children":[]}]}]},{"type":"text","value":"REST"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"REST (Representational State Transfer) is an architectural style rather than a\nstandard. The main idea is that the URI names a resource(s) "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"and"}]},{"type":"text","value":" operation,\nnot the page. A RESTful API observes 6 constraints listed in Fielding's 2000\ndissertation. By observing these constraints applications gain valuable\nfeatures such as improved performance and scalability."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"ul","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Client-server"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Stateless:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"blockquote","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"each request from client to server must contain all of the information\nnecessary to understand the request, and cannot take advantage of any\nstored [session] context on the server. Session state is therefore kept\nentirely on the client."}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Cache: "}]},{"type":"text","value":"\n"},{"type":"element","tagName":"blockquote","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"data within a response to a request [must] be implicitly or explicitly\nlabeled as cacheable or non-cacheable"}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Uniform interface: A RESTful URI is self-contained, i.e. includes an\nidentification of the resource and what to do. If we have representation of a\nresource, we have enough information to modify it (including delete that\nresource). Responses may include hyperlinks to discover additional RESTful\nresources (termed Hypermedia As The Engine Of Application State or HATEOAS)."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Layered system: Each component can't see beyond the immediate next layer,\nenable intermediate layers to support load-balancing and other optimizations."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Code on demand: Servers can extend client by transmitting executable code\n(e.g. JavaScript)"}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"A more approachable definition might be... a RESTful API uses the URI to\nidentify and interact with resources. The URI is typically the \"noun\" and the\nHTTP method the \"verb\". More specifically:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"ol","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"The API is expressed as actions on specific resources (identified in the URI\nitself, i.e. the URI is self-contained)"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Use HTTP verbs as actions (in line with their meaning in HTTP specification)"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Responses can include hyperlinks to discover additional RESTful resources\n(HATEOAS)"}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"comment","value":" https://martinfowler.com/articles/richardsonMaturityModel.html "},{"type":"text","value":"\n"},{"type":"element","tagName":"h3","properties":{"id":"an-api-for-films"},"children":[{"type":"element","tagName":"a","properties":{"href":"#an-api-for-films","ariaLabel":"an api for films permalink","className":["anchor"]},"children":[{"type":"element","tagName":"svg","properties":{"ariaHidden":"true","focusable":"false","height":"16","version":"1.1","viewBox":"0 0 16 16","width":"16"},"children":[{"type":"element","tagName":"path","properties":{"fillRule":"evenodd","d":"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"},"children":[]}]}]},{"type":"text","value":"An API for films"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Consider the movies in our Film Explorer. They have an "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"id"}]},{"type":"text","value":", a "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"title"}]},{"type":"text","value":" and several other properties. What are some ways that we could request a film(s)?"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"GET /films/135397\nGET /api/v2/films/135397\nGET /films?title=Jurassic+World"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Note that the first two routes uniquely identifies a resource (i.e. a specific\nmovie) and could be part of a \"RESTful\" API. The third could identify a unique\nmovie, or not, if there are multiple movies with the same title. It is still\n\"RESTful\" but may best describe a \"listing\" operation instead of a single\nmovie. The "},{"type":"element","tagName":"a","properties":{"href":"https://cloudplatform.googleblog.com/2017/10/API-design-choosing-between-names-and-identifiers-in-URLs.html"},"children":[{"type":"text","value":"Google Cloud Platform\nBlog"}]},{"type":"text","value":"\nfor instance recommends \"Identifiers are for look-up. Names are for search.\"\nThus we could think of the third route as listing all movies with Jurassic\nWorld as the (or in the) title."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"In all cases the actions would be to read and return the specified data. In\nwhat format?  Could be HTML, JSON, etc. depending on the specification of the\nrequest (via the "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"Accept"}]},{"type":"text","value":" header)."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h3","properties":{"id":"example-with-film-explorer"},"children":[{"type":"element","tagName":"a","properties":{"href":"#example-with-film-explorer","ariaLabel":"example with film explorer permalink","className":["anchor"]},"children":[{"type":"element","tagName":"svg","properties":{"ariaHidden":"true","focusable":"false","height":"16","version":"1.1","viewBox":"0 0 16 16","width":"16"},"children":[{"type":"element","tagName":"path","properties":{"fillRule":"evenodd","d":"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"},"children":[]}]}]},{"type":"text","value":"Example with Film Explorer"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Film Explorer API (note we typically use the colon to identify parameters):"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"ul","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"GET "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"/api/films"}]},{"type":"text","value":": List all the films"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"GET "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"/api/films/:id"}]},{"type":"text","value":": Read the film with with id == "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":":id"}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"PUT "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"/api/films/:id"}]},{"type":"text","value":": Update the film with id == "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":":id"}]},{"type":"text","value":" with the request body"}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h4","properties":{"id":"crudl"},"children":[{"type":"element","tagName":"a","properties":{"href":"#crudl","ariaLabel":"crudl permalink","className":["anchor"]},"children":[{"type":"element","tagName":"svg","properties":{"ariaHidden":"true","focusable":"false","height":"16","version":"1.1","viewBox":"0 0 16 16","width":"16"},"children":[{"type":"element","tagName":"path","properties":{"fillRule":"evenodd","d":"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"},"children":[]}]}]},{"type":"text","value":"CRUD(L)"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"The basic operations on a RESTful resource are typically abbreviated CRUD:\nCreate, Read, Update and Delete (along with List)."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"For the specific resource "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"/api/films/135397"}]},{"type":"text","value":":"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"ul","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"GET: Read a representation of the movie with id of 135397 (a GET operation shouldn't have side effects)"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"PUT: Update the specified movie by replacing it entirely"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"POST: Not used"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"DELETE: Delete the specified movie"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"PATCH: Update part of the specified movie"}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"For the collection of resources '/movies':"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"ul","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"GET: List all the movies"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"PUT: Update the collection of movies by replacing it entirely with another collection"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"POST: Create a new movie in the collection and return its id (and perhaps other information)"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"DELETE: Delete the collection"}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h4","properties":{"id":"non-crud-operations"},"children":[{"type":"element","tagName":"a","properties":{"href":"#non-crud-operations","ariaLabel":"non crud operations permalink","className":["anchor"]},"children":[{"type":"element","tagName":"svg","properties":{"ariaHidden":"true","focusable":"false","height":"16","version":"1.1","viewBox":"0 0 16 16","width":"16"},"children":[{"type":"element","tagName":"path","properties":{"fillRule":"evenodd","d":"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"},"children":[]}]}]},{"type":"text","value":"Non-CRUD operations?"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Search? Think of the resource as the list of movies matching the query..."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"GET /films/search?q=Jurassic"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"What about \"Add to my favorites\" or \"Add to shopping cart\"? When it seems awkward to express an operation in terms of your existing resources, ask whether there is another resource type waiting to be defined."}]},{"type":"text","value":"\n"},{"type":"comment","value":" \nhttps://gist.github.com/hjr3/2289546\nhttps://github.com/alexpls/cart_rest_example\n "},{"type":"text","value":"\n"},{"type":"element","tagName":"h2","properties":{"id":"rest-and-react"},"children":[{"type":"element","tagName":"a","properties":{"href":"#rest-and-react","ariaLabel":"rest and react permalink","className":["anchor"]},"children":[{"type":"element","tagName":"svg","properties":{"ariaHidden":"true","focusable":"false","height":"16","version":"1.1","viewBox":"0 0 16 16","width":"16"},"children":[{"type":"element","tagName":"path","properties":{"fillRule":"evenodd","d":"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"},"children":[]}]}]},{"type":"text","value":"REST and React"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"We can implement this fetch in a variety of container components. When and where exactly?"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"We are going to make use of React's other type of hook -- the "},{"type":"element","tagName":"a","properties":{"href":"https://reactjs.org/docs/hooks-effect.html"},"children":[{"type":"text","value":"effect hook"}]},{"type":"text","value":". "}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"At their simplest, effect hooks allow us to provide a function to be run after our component has rendered. In this case, we are fetching data from a remote server, so we need to show "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"something"}]},{"type":"text","value":" on the screen while this longer process happens. This adds a little bit of complexity because we need to consider how to render our component both with and without data."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["gatsby-highlight"],"dataLanguage":"javascript"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-javascript"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-javascript"]},"children":[{"type":"element","tagName":"span","properties":{"className":["token","keyword"]},"children":[{"type":"text","value":"let"}]},{"type":"text","value":" filmContents "},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":"="}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"("}]},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":"<"}]},{"type":"text","value":"h2"},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":">"}]},{"type":"text","value":"Loading"},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":"..."}]},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":"<"}]},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":"/"}]},{"type":"text","value":"h2"},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":">"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":")"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":";"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"span","properties":{"className":["token","keyword"]},"children":[{"type":"text","value":"if"}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"("}]},{"type":"text","value":"films"},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":")"}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"{"}]},{"type":"text","value":"\n  filmContents "},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":"="}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"("}]},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":"<"}]},{"type":"text","value":"FilmTableContainer\n    films"},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":"="}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"{"}]},{"type":"text","value":"films"},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"}"}]},{"type":"text","value":"\n    "},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":"..."}]},{"type":"text","value":"\n  "},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":"/"}]},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":">"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":")"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":";"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"}"}]}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Normally, the effect hook will run every single time the component is rendered. For our purposes, we want a little bit more control. We can pass a second argument to the hook that is a list of props and state variables. React will only run the hook function if one of the values changes. If the array is left empty, the hook will run a single time."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h3","properties":{"id":"asynchronous-data-access-and-promises"},"children":[{"type":"element","tagName":"a","properties":{"href":"#asynchronous-data-access-and-promises","ariaLabel":"asynchronous data access and promises permalink","className":["anchor"]},"children":[{"type":"element","tagName":"svg","properties":{"ariaHidden":"true","focusable":"false","height":"16","version":"1.1","viewBox":"0 0 16 16","width":"16"},"children":[{"type":"element","tagName":"path","properties":{"fillRule":"evenodd","d":"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"},"children":[]}]}]},{"type":"text","value":"Asynchronous data access (and Promises)"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"There are several ways to request remote resources in JavaScript (all based on the same underlying technology). We will use the now widely available "},{"type":"element","tagName":"a","properties":{"href":"https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch"},"children":[{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"window.fetch"}]}]},{"type":"text","value":" function. "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"fetch"}]},{"type":"text","value":" has replaced "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"XMLHttpRequest"}]},{"type":"text","value":" (XHR) in many settings."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"fetch()"}]},{"type":"text","value":" has a number of options, but at its most basic, it is just "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"fetch(url)"}]},{"type":"text","value":". The return value is not the response, but a "},{"type":"element","tagName":"a","properties":{"href":"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises"},"children":[{"type":"text","value":"Promise"}]},{"type":"text","value":" with which we can obtain that response."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Recall that the browser is event-based. A typical pattern is to launch an "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"asynchronous"}]},{"type":"text","value":" operation, such as a network request, in the background and supply a callback function to be invoked when the result is available. In the meantime the original function returns and execution continues (enabling the UI to remain responsive)."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"But when you need a callback inside a callback, the deeply nested structured (i.e. callbacks, inside callbacks, inside callbacks), like below, becomes difficult to reason about."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"someAsyncOperation(someParams, (result, error) => {\n  // Do something with the result or error\n  newAsyncOperation(newParams, (result, error) => {\n    // Do something more...\n  });\n});"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Instead we can use a chain of Promises to \"flatten\" the nested callbacks:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"someAsyncOperation(someParams)\n.then((result) => {\n  // Do something with the result\n  return newAsyncOperation(newParams);\n})\n.then((result) => {\n  // Do something more\n})\n.catch((error) => {\n  // Handle error\n});"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"From "},{"type":"element","tagName":"a","properties":{"href":"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise"},"children":[{"type":"text","value":"MDN"}]},{"type":"text","value":":"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"blockquote","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"A Promise is a proxy for a value not necessarily known when the promise is\ncreated. It allows you to associate handlers with an asynchronous action's\neventual success value or failure reason. This lets asynchronous methods\nreturn values like synchronous methods: instead of immediately returning the\nfinal value, the asynchronous method returns a promise to supply the value at\nsome point in the future."}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Thus a Promise is one of three states:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"ol","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Pending: Initial state, neither fulfilled or rejected"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Fulfilled: The operation as has completed successfully"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Rejected: The operation has failed."}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"A Promise has a "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"then"}]},{"type":"text","value":" method that invokes the supplied callback when the Promise is "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"fufilled"}]},{"type":"text","value":" with a concrete value. That callback can return a new Promise, or if it returns a concrete value, that value will be wrapped in a fulfilled Promise. Alternately if there is an error or other failure, the Promise is "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"rejected"}]},{"type":"text","value":" and the reject function in the chain (supplied to the "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"catch"}]},{"type":"text","value":" method here) is invoked. The "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"then"}]},{"type":"text","value":" and "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"catch"}]},{"type":"text","value":" methods return promises to facilitate the chaining we saw above."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"If "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"fetch"}]},{"type":"text","value":" succeeds, it resolves to a "},{"type":"element","tagName":"a","properties":{"href":"https://developer.mozilla.org/en-US/docs/Web/API/Response"},"children":[{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"Response"}]}]},{"type":"text","value":" object (an HTTP response), from which we can obtain the status of the response, the type, header, and contents (which can be accessed in a variety of formats)."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["gatsby-highlight"],"dataLanguage":"javascript"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-javascript"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-javascript"]},"children":[{"type":"element","tagName":"span","properties":{"className":["token","function"]},"children":[{"type":"text","value":"fetch"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"("}]},{"type":"element","tagName":"span","properties":{"className":["token","string"]},"children":[{"type":"text","value":"'/api/films/'"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":")"}]},{"type":"text","value":"\n  "},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"."}]},{"type":"element","tagName":"span","properties":{"className":["token","function"]},"children":[{"type":"text","value":"then"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"("}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"("}]},{"type":"element","tagName":"span","properties":{"className":["token","parameter"]},"children":[{"type":"text","value":"response"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":")"}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":"=>"}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"{"}]},{"type":"text","value":"\n    "},{"type":"element","tagName":"span","properties":{"className":["token","keyword"]},"children":[{"type":"text","value":"if"}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"("}]},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":"!"}]},{"type":"text","value":"response"},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"."}]},{"type":"text","value":"ok"},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":")"}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"{"}]},{"type":"text","value":"\n      "},{"type":"element","tagName":"span","properties":{"className":["token","keyword"]},"children":[{"type":"text","value":"throw"}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","keyword"]},"children":[{"type":"text","value":"new"}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","class-name"]},"children":[{"type":"text","value":"Error"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"("}]},{"type":"text","value":"response"},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"."}]},{"type":"text","value":"statusText"},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":")"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":";"}]},{"type":"text","value":"\n    "},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"}"}]},{"type":"text","value":"\n    "},{"type":"element","tagName":"span","properties":{"className":["token","keyword"]},"children":[{"type":"text","value":"return"}]},{"type":"text","value":" response"},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"."}]},{"type":"element","tagName":"span","properties":{"className":["token","function"]},"children":[{"type":"text","value":"json"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"("}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":")"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":";"}]},{"type":"text","value":"\n  "},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"}"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":")"}]},{"type":"text","value":"\n  "},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"."}]},{"type":"element","tagName":"span","properties":{"className":["token","function"]},"children":[{"type":"text","value":"then"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"("}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"("}]},{"type":"element","tagName":"span","properties":{"className":["token","parameter"]},"children":[{"type":"text","value":"data"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":")"}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":"=>"}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"{"}]},{"type":"text","value":"\n    "},{"type":"element","tagName":"span","properties":{"className":["token","function"]},"children":[{"type":"text","value":"setFilms"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"("}]},{"type":"text","value":"data"},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":")"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":";"}]},{"type":"text","value":"\n  "},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"}"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":")"}]},{"type":"text","value":"\n  "},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"."}]},{"type":"element","tagName":"span","properties":{"className":["token","function"]},"children":[{"type":"text","value":"catch"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"("}]},{"type":"element","tagName":"span","properties":{"className":["token","parameter"]},"children":[{"type":"text","value":"err"}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":"=>"}]},{"type":"text","value":" console"},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"."}]},{"type":"element","tagName":"span","properties":{"className":["token","function"]},"children":[{"type":"text","value":"log"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"("}]},{"type":"text","value":"err"},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":")"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":")"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":";"}]},{"type":"text","value":" "}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Why not just "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"setFilms(response.json())"}]},{"type":"text","value":"? "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"response.json()"}]},{"type":"text","value":" returns\na Promise that will resolve with the result of parsing the response as JSON (the parsing is an asynchronous operation).  The second "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"then"}]},{"type":"text","value":" function will be invoked when the "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":".json()"}]},{"type":"text","value":" Promise resolves."}]},{"type":"text","value":"\n"},{"type":"comment","value":" \nAPI design: https://www.gitbook.com/book/geemus/http-api-design/details\nhttps://docs.microsoft.com/en-us/azure/architecture/best-practices/api-design#organize-the-api-around-resources\n "}],"data":{"quirksMode":false}},"frontmatter":{"path":"/lectures/lecture7-rest","title":"Lecture 7 - Rest","name":"Lecture 7 - Rest"},"parent":{"__typename":"File","id":"ba004a52-e822-551b-b6e1-d821f889143c","name":"lecture7-rest","modifiedTime":"Oct 1 2019 14:42"}}},"pageContext":{"isCreatedByStatefulCreatePages":false}}}