State, Time, and Concurrency
This is a modal window.
The media could not be loaded, either because the server or network failed or because the format is not supported.
Formal Metadata
Title |
| |
Title of Series | ||
Number of Parts | 28 | |
Author | ||
License | CC Attribution - ShareAlike 3.0 Unported: You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal and non-commercial purpose as long as the work is attributed to the author in the manner specified by the author or licensor and the work or content is shared also in adapted form only under the conditions of this | |
Identifiers | 10.5446/33649 (DOI) | |
Publisher | ||
Release Date | ||
Language |
Content Metadata
Subject Area | ||
Genre | ||
Abstract |
|
EmberConf 201713 / 28
9
13
14
16
17
18
23
24
00:00
Concurrency (computer science)State of matterCodeVideoconferencingCore dumpProof theoryOperations researchMilitary operationSynchronizationComputer programmingNP-hardCASE <Informatik>FluxPressure volume diagramHydraulic jumpRule of inferenceSerial portExecution unitEuclidean vectorSoftware frameworkSpiralGroup actionMenu (computing)Real numberMathematicsMultiplication signGroup actionDemosceneInformationQuicksortProduct (business)Directed graphResultantExistential quantificationFeedbackBitTrailData storage deviceVideo gameArithmetic meanRadon measureNumberLine (geometry)Client (computing)Goodness of fitOperator (mathematics)Degree (graph theory)Digital photographyWeb-DesignerMobile appElectronic mailing list1 (number)Service (economics)MathematicsChord (peer-to-peer)Form (programming)Core dumpMatching (graph theory)Server (computing)Right angleUniform resource locatorObject (grammar)MultiplicationLogical constantCodeAreaCodeFluxCASE <Informatik>Water vaporComputer programmingCategory of beingTemplate (C++)FlagSingle-precision floating-point formatConcurrency (computer science)State of matterSequenceWordSet (mathematics)Proof theorySpiralConnectivity (graph theory)Software frameworkLatent heatPrimitive (album)2 (number)Structural loadFreewareMobile WebSuite (music)Task (computing)Error messageSoftware bugXML
07:38
Simultaneous localization and mappingSet (mathematics)Primitive (album)Task (computing)SynchronizationOperations researchConcurrency (computer science)Menu (computing)System callFunction (mathematics)Equivalence relationDefault (computer science)Euclidean vectorSequenceGroup actionConstraint (mathematics)Local ringState of matterPresentation of a groupTask (computing)ResultantInstance (computer science)QuicksortComputer programmingSet (mathematics)State of matterGenerating functionMultiplication signNumberConcurrency (computer science)Arithmetic meanConstraint (mathematics)FlagDefault (computer science)CASE <Informatik>CodeLine codeCategory of beingExpressionSocial classSoftware testingConnectivity (graph theory)ProteinGroup actionOperator (mathematics)Different (Kate Ryan album)Data storage deviceElectronic mailing listMatching (graph theory)Content (media)MereologyRight angleComputer configurationGame controllerBitDrop (liquid)SurfaceSound effectInformation technology consultingSpectrum (functional analysis)Queue (abstract data type)Process (computing)Sinc functionWeightLogicSemiconductor memoryCountingDerivation (linguistics)Point (geometry)InformationArithmetic progressionDeclarative programmingRow (database)1 (number)AreaControl flowComputer filePrimitive (album)Functional (mathematics)WordRevision controlRouter (computing)Finite differenceLine (geometry)Latent heatError messageData conversionVideo game consoleUser interfaceComputer animation
15:16
GUI widgetTask (computing)Moment (mathematics)Video trackingScalable Coherent InterfaceCategory of beingHausdorff dimensionLimit (category theory)Configuration spaceBookmark (World Wide Web)SynchronizationTwitterSoftware frameworkFormal languageInstance (computer science)Complete metric spaceException handlingError messageBookmark (World Wide Web)Category of beingGUI widgetInstance (computer science)Task (computing)Mobile appCodeLine (geometry)1 (number)Row (database)Vector potentialConnectivity (graph theory)CASE <Informatik>QuicksortSocial classHookingEndliche ModelltheorieLimit (category theory)Dimensional analysisFormal languageError messageConfiguration spaceMultiplication signMoment (mathematics)Proxy serverVariety (linguistics)BuildingNumberMathematicsSound effectCountingSoftware developerBootstrap aggregatingException handlingComplete metric spaceConcurrency (computer science)Computer programmingOverlay-NetzFlagRoutingLink (knot theory)State of matterSoftware repositoryObject (grammar)Level (video gaming)Game theorySlide ruleDrop (liquid)TwitterConstraint (mathematics)TouchscreenBitSoftware frameworkControl flowPoint (geometry)Boolean algebraFilm editingWindowSoftware testingCheat <Computerspiel>Degree (graph theory)Single-precision floating-point formatService (economics)Message passingRight angleStructural loadEstimatorOrder (biology)Digital electronics4 (number)Bit rateElectronic visual displayRootMassGoodness of fitComputer animation
22:53
Very long instruction wordDefault (computer science)Euclidean vectorConcurrency (computer science)GUI widgetTask (computing)Instance (computer science)TorusSimultaneous localization and mappingFluxSign (mathematics)Limit (category theory)Thomas KuhnExecution unitDrum memoryPointer (computer programming)Local area networkState of matterRootKolmogorov complexityTablet computerHausdorff dimensionImperative programmingSynchronizationOperations researchCodeCombinatoricsCategory of beingDeclarative programmingSoftware frameworkCategory of beingRevision controlTask (computing)Instance (computer science)Error messageData storage deviceState of matterMultiplication signResultantWordEntropie <Informationstheorie>Pattern languageDistribution (mathematics)Complete metric spaceDerivation (linguistics)Constraint (mathematics)MathematicsQuicksortCodeSound effectExecution unitConcurrency (computer science)GUI widgetSlide ruleProxy serverCASE <Informatik>Element (mathematics)MultiplicationSoftware testingServer (computing)TouchscreenBitPairwise comparisonComplex (psychology)NeuroinformatikRootInformationOperator (mathematics)Object (grammar)Web pageDisk read-and-write headTerm (mathematics)Matrix (mathematics)Musical ensembleBookmark (World Wide Web)SoftwareSoftware maintenanceLogicWebsiteFunctional (mathematics)Directed graphTrailActive contour modelParticle systemCasting (performing arts)Integrated development environmentDot productDifferent (Kate Ryan album)User interfaceLevel (video gaming)CausalityTemplate (C++)LengthMaxima and minimaRadio-frequency identificationImperative programmingDeclarative programmingInterleavingLatent heatLoop (music)Form (programming)CombinatoricsXML
30:31
XML
Transcript: English(auto-generated)
00:12
So my name's Alex. I'm talking today about state time and concurrency. And this is a high school senior photo so as to establish some degree of humility. I'm the former
00:27
core team member, now Ember core team emeritus. I work at a company called Future Proof Retail. We have built and maintained a suite of Ember apps that kind of target retailers, grocery stores, the most popular of the apps being a mobile line free checkout app where
00:42
you can scan items on your phone and checkout and skip the line. And so I've got plenty of experience the last few years doing mobile apps and dealing with concurrency. So state time and concurrency. Maybe let's define a few terms. So state is the data in your app that changes over time. Async operations which might be admitted or kicked
01:03
off in your app take time and usually cause state to change. And concurrency is any time that you have more than one async operation happening at the same time. And I would sort of argue that the user is kind of an async operation. The user will get impatient and
01:20
will triple click the form submit button and will click the refresh button if things don't load fast enough. So any app that has any async on its own, any timer, any Ajax request is already concurrent because there's always the user. And concurrent programming is pretty hard, still it's pretty hard. Unfortunately it's pretty much all
01:41
that web development programming is. So Ember concurrency is an add-on that I wrote maybe a little bit more than a year ago that helps you manage and deal with state time and concurrency. And it's one of the more popular Ember add-ons. Maybe a quick show of hands, who uses Ember concurrency in a production app? It's pretty good. It's
02:02
like 50% or so. So to sort of highlight what's actually difficult, I'm actually going to stick with a pretty simple use case that gets hairy pretty quickly. So this is actually a use case that's lifted from my own app for the mobile checkout where one of the first things that you have to do is geolocate, get your latitude
02:22
and longitude coordinates and then forward that information to the server so that the server can tell you nearby locations that are supported that you can check out at using this app. And so we're going to start off doing this in a very vanilla typical Ember fashion. We're just going to have a action called submit form. It's going to make use of a geolocation service. It's going to
02:41
make use of a store, a data store, and it's going to say geolocation.getcords. This returns a promise. When the promise fulfills, we're going to take the coordinates that were returned from the successful hopefully geolocation request and we're going to forward that to get nearby stores and that's going to return a promise that fulfills when we have a list of stores that are nearby.
03:01
Then we're going to take that result and we're going to set it as a property on this component so that it's exposed to the template and the template can render it. So if I click this button, it's going to take two seconds and then the results are going to show up. There's a flux potle, there's a flux central, there's the fluxes R us, there's transclusions R us, which is a competitor, and throughout these examples they'll be moving around in
03:23
the world so the results will change. So this is not really ready for production. You wouldn't ship this because clicking this button gives you absolutely no feedback as to the fact that something's happening behind the scenes. So let's fix that. The first thing we'll do is we'll add a is submitting flag and we're going to set it to true at the beginning of the action.
03:44
We're going to set it to false right after we get the results back. So we can use that is submitting to drive the state of the button. So now it says finding and there's at least some feedback that something is happening in the app. But we're still not done because if I button mash, which you can't tell that I'm doing, but if I tap this a bunch of times in a row, I'm
04:03
actually kicking off a bunch of async operations and getting coordinates multiple times and asking the server multiple times to find nearby locations. So we're still not ready to actually ship this to production. So really this is an issue of unwanted concurrency. We've made it really easy to kick off an async operation, but we've also made it really easy to kick off an async
04:24
operation while one's already running and that's the definition of concurrency and we want to constrain that. So we just add a single line of code. We reuse this is submitting flag and we check it at the beginning of the action and if it's true that means we've already kicked off an action before and it's not done yet so just return early. So if I button mash this at least solves
04:41
the problem of kicking off multiple operations that just make sure that only one fires off. Are we done? Are we good? Unfortunately no because we log into our error reporter, we log in a bug snag or whatever and we're seeing that there's a bunch of client-side errors along the lines of calling set on destroyed object. We get so frustrated with Ember that we throw out
05:03
all of our code and we rewrite and react and apply the same methodologies only to realize that we run into the same error with slightly different copy which says this usually means you called set state on unmounted component. So this is just a highlight that this is not an Ember specific thing this is something that frameworks in general that don't really give you great async
05:23
primitives or concurrency primitives it's something that you have to deal with kind of everywhere. But let's press on we're gonna stick with our quickly degrading Ember based example and so we had a little bit of defensive programming we check if this is destroyed so because components
05:44
extend Ember object, Ember object exposes whether an object is destroyed you can just check this that is destroyed and return early so that these potentially dangerous sets don't happen right and I don't really have any code to validate this is actually working it's honestly when when you
06:01
start really adding these to your code base it's you're probably not testing each one maybe you are but it's everywhere and that's just such a harrowing task so that works but then you get a feature request from Satan who says it's good but can you add a you had a cancel button we had some clients
06:22
that their geolocation isn't great they'd like to cancel and maybe geolocate via some other means or prove that they're at the store and then so you continue the downward spiral and I didn't actually finish writing this piece of code it's broken if you click click find nearby stores and click it
06:41
again it like weirdly undoes itself because why would I spend so much time writing shitty code just to make it work so this doesn't work but you could imagine doing something where you track a sequence number of how many operations you've done maybe you could also keep track of the last promise that you would have stashed from the result of here and then every one of
07:04
these callbacks you check if it's the most recent promise and if not that means it was called again or it was cancelled and then you need to you know it's just the worst it's the worst so I'm gonna go on a limb and say that you've probably bargained with a designer or somebody making a feature request that said or you basically had to water down what they're asking
07:24
you to do because you didn't know how to cancel an async operation I know I have I'm assuming as everyone else is probably guilty of that that's fine you don't need to like build out every single harebrained feature that a designer asks for but it sucks when you have to say no when ember tells you
07:41
no or react or whatever says this is too hard to do and it really shouldn't be so this is where ember concurrency comes in and so I've rewritten the previous code to use the so-called ember concurrency tasks and really the active ingredients are just this part here where you're getting coordinates and then also passing it to get the nearby list of stores but this
08:04
actually hits all the use cases all the corner cases from the previous code if I if I button mash this thing a bunch of times in a row it's not going to keep on sending me progressive results and also I can cancel it and it doesn't break I don't really want to open the console and risk that a live
08:22
presentation but there's no weird errors are set on destroy or anything like that it's just safe and I'll kind of go into different things that really go into it but if you've never seen ever concurrency before if this is new to you it's probably a lot of information so but well I just want to point out maybe a few things that are that are interesting about this
08:41
example one is that there's no is submitting flag yeah the things people get excited about it ember conf so there's no is submitting flag so somehow that is addressed there's no is destroyed kind of defensive programming checks there's no check to see if I'm already running because that
09:00
means you know I have to prevent concurrency by returning early and this might be new to the the ember concurrency veterans in the crowd but there's no sets at all in this line of code there's no setting a sideways result property or anything so this is actually going to be when I'm sort of focusing more on this and this presentation than I have before deal
09:27
with it so what actually is ember concurrence I show you an example of using it but like is it a bunch of different api's is just one thing it's really just one thing it's a task primitive and 99% of ember
09:41
concurrency API involves using tasks and really a task is like usually it means you took an action something that was an actions hash and you moved it to his task and use the generator function syntax and you implement it as a task instead of an action so what does a task give you it gives you a better syntax for expressing async operations similar to a single weight but in a manner that gives you cancellation and supports cancellation
10:04
first class it is also a declarative API for constraining concurrency so not only can you express these operations in a nicer fashion that's cancelable but you have an API that prevents these operations from happening at the same time using any number of approaches and what I'm focusing on more in this
10:21
conversation is it gives you a bunch of derived state so as an example of the syntax side of things I've implemented the same async operation twice once as an ember concurrency task and one as an async function and they both just count to three here's the task running here's the task cancelling after two here's the async function variant but this button is not actually
10:44
possible to implement easy in any easy simple embery feeling manner because async functions as defined by the job specification are not cancelable they're lovely but the fact that they can't be cancelled is kind of a deal breaker because it means the only way that you can cancel is basically any place
11:02
that there's an await you'd have to add some logic after the await to see if you've been cancelled that's kind of the exact sort of defensive programming that you want to avoid and there's no TC39 spec for async function cancellation there was but it was withdrawn a few months back and latest I've heard is that we should probably get used to just using
11:23
generator functions for a while which ever currency has been using for a year anyway so we don't have to change anything from our end and if this is like sad news if you'd rather use the nice async function syntax at least you can take some solace in the fact that the way ember concurrency treats generator functions is semantically identical to async functions the only
11:41
thing you need to know to do is take any instance where you're awaiting a promise and replace it with a yield which is the generator function keyword that you use and not await so back to all the things that tasks do it's not just syntax it's also a declarative API for constraining concurrency and always
12:01
when I say constraining concurrency it usually just means make sure only one of these is running at a time so yeah that's this really often the hardest part it's not that ember concurrency is empowering you to just like spin off six billion different asynchronous tasks at the same time it's really UI driven and UIs are usually dealing with the problem of how do I make sure that things are properly cleaned up and canceled and only one
12:23
thing is happening at a time so this is where the so-called task modifier API comes in so if you just run an ember concurrency task embers not ever concurrency isn't going to prevent these from overlapping in any way that's that's the default there are no concurrency constraints if you want to constrain concurrency make sure that one thing is running you've
12:43
got a few options there's a few ways that you can do that one is that is to use drop drop is probably the most common one and it's the one that we use in the example before it means that if there's already an instance of this task running then any attempt to perform a new task gets immediately canceled and any canceled task instance that is canceled before it can even
13:02
start we just say it's dropped and hence that's the the word that we use for the task modifier and Q is a different version that we can use I never use and Q I thought I would but no one really use it I'm a handful of people do but it's kind of it's a little bit too much too much magic in practice but the other one that is really common and popular I think the
13:23
most popular ones are dropping restartable and there's one or two more that I'm not gonna bring up but restartable is when a task is already running if you try and perform it again it's going to cancel any prior instances and then that makes room for the new one to run and it runs immediately some of you may or may not know that there's a thing
13:41
called task groups I don't use these but I wanted to sort of just highlight that they exist so all the previous examples show you how to constrain concurrency for a single task but what if there's different tasks different operations and you want to make sure that only one runs at a time what you can do is you can use a task group you can say that upload file is a task that is of the my group task and my group is defined as
14:03
a task group that is restartable and what that means is that if any of these if you try to perform any of the tasks in one of these groups it's going to cancel any prior instances also in that group to make room for the new one to run so as I go between these cancel buttons every time I perform it it's canceling the other ones going there are use cases for this I haven't
14:23
actually personally used it yet but I definitely got started on it pretty early because people that were early adopters had use cases for this sort of thing and so this is all stuff that I presented on before but I don't really think I've talked too much about the so-called derived state which I want to focus on a little bit more and by derived state I'm just mean
14:43
there's always an opportunity and we're always gonna allow the flexibility to let you track your own state by introducing another property on a component or controller or router or whatever and you can just manually update the state of that over time so you could have used is my test running you could have done is submitting from the earlier example
15:01
and then put a bunch of this dot sets to update that value over time but instead of doing that there's actually a lot of properties that are kind of built into tasks and these tasks instances that you should know about because they can save you a lot of pain a lot of error prone code so it's a very basic example of some stuff that's given to you for free is
15:22
running I didn't actually show you any of the template code before I will soon for that example with a geolocation but if you have a task that's called ship widgets I'm probably gonna screw up that one if I say it a few times ship widgets and you perform it then is running is going to go
15:40
to true perform count is going to increment it's one of the newer ones concurrency is always going to reflect the number of the current number of running tasks so this one doesn't have any concurrency constraints so if I just button mash this thing concurrency is going to go up and then it's going to go down and if anybody ends up you know playing around these slides later it's kind of a fun game to see how high you can get concurrency before it goes back down somebody actually cheated and made
16:03
like a little jQuery plug-in to tap the button a million times again the things people get excited about so just with there's way more derived state than just what I showed on the previous slide but I wanted to sort of highlight a quick thing because I don't think of the very many people appreciate this aspect of ever current concurrency so much and I keep tabs of how people are
16:25
actually using this stuff there's like public github repos that use it sometimes people will send me code snippets if it's you know something that came out even they're using a pneumatic ember concurrency but still came out a little weird so one that I've seen a handful of times it's almost as if
16:45
people don't even know the API sort of exists or they just haven't sort of practiced this style of thinking but if ship widgets has a is shipping widget boolean property that it's managing the state of then it's tempting to say
17:01
okay I'll just set it to true at the beginning of the task and set it to false at the end but there's obviously some problems with it it's completely redundant why would you ever introduce more state that you need to track yourself and probably get wrong when you can use just something that's built in it's a it's a point of failure your chances are you're probably going to reorganize when these things get set to true and false and it's gonna
17:23
break in very subtle ways because there's all when you write code this way there's all these timing dependencies for when you set properties and when you decide to mutate some property on a component and it's actually broken it's not just error prone this is actually wrong because if you were to cancel this task while it's paused on this line of code then this
17:43
line is never gonna get run and you're gonna like you're gonna have is shipping widget be set to true even though nothing's actually shipping there's another instance that I didn't write down here but I kind of just struck me this can run concurrently because there's no constraints and if you run this eight times in a row the first task to get to this line of code is
18:01
gonna say is shipping widget false even though there might be seven more instances that are still running so use derived state when you can because you're probably gonna get it wrong otherwise because we're dealing with concurrency concurrent program is really hard so use what's what's given to you and there's sort of a minor problem I want to point out it's not as big as the other issues but every property that you introduce every piece
18:21
of state also needs to have a name and developers like to bicker over how to name things do what you call this flag is shipping widgets or is ship widgets running maybe another developer had to have a problem with that because that meant you'd need to capitalize the S and then it's harder to grep and so there's all these little death by a thousand paper cuts problems that you can avoid when you just use the state that is kind of built into a
18:44
task and then you can just very easily just grep your program and see what are all the components that updates when ship widgets state changes so it's a minor problem but it kind of comes up a lot and it's one of these cases where it's just a little bit of convention that prevents a lot of like drift between
19:02
apps between developers so if this task returns one two three you would think that there's some way that we could actually access that and you already saw an example where you did with the the geolocating example we didn't use dot set so obviously somehow we were taking the return value of that task and bring it to the screen so would it be ship widgets dot value
19:23
would be something else and so I want to talk about how ever concurrency is put a lot of effort a lot of that a lot of the API that design that went into it is there to respect the fourth dimension the fourth dimension being time because there's a lot of I've seen a lot of attempts to build
19:42
nice conventions over promises promise proxies but they don't really they don't really they kind of the conventions cut a little too deep I think is one way of putting it they kind of choose a happy path that plays favorites and doesn't actually make it easy to design a variety of
20:02
of async use cases so we want to we want to honor convention over configuration but we don't want to take it so far that actually hurts our own creativity so convention over configuration is great when these shared battle-tested conventions don't limit your potential don't limit your creativity but when they do and when they play favorites when the API's make
20:24
certain use cases and data flows really easy to do but others really hard and sort of make you feel bad for even trying them that's obviously not good so I'm trying to avoid that with ever concurrency and I think an example of this and it's kind of a API that I worked on a few years back but the the fact that you're very much encouraged to load models and the
20:44
route model hook and it kind of is the sort of a subtle shame that if you ever try to do data loading and components the framer just kind of just slightly punishes you for wanting to do that but if you don't and you load all of your data in the model hook then you're sort of in a class of ember apps that sort of feel very similar to all the other ones you know
21:03
that when you click a link it's you might use a loading route and it's cost some overlay to go over there and it just doesn't go there immediately it's just you can tell you're dealing with like a 2013 2014 ember app in the same way that if you know you started off using Twitter bootstrap the CSS framework and you never really fully separated and built your own thing then
21:24
you it's just another app that looks like a Twitter bootstrap app so this is sort of that effect applied to when convention over configuration picks sort of favorites with certain use cases so ever concurrency doesn't always provide a particular convention but it has gives you conventional language to
21:43
express it doesn't choose for you how you what kind of data you want to display what is the most recent successful value from a task that completed oh this will all make sense in just a moment I promise I know I'm mixing the words up but this is a long way of saying that isn't just ship widgets dot value it's ship widgets dot last successful value and
22:03
last successful could actually be any number of things so let's actually dive into what that means so it's not dot value this is always going to be undefined but you could use ship widgets dot last dot value or you could use last successful that value so what are these you see what are these properties I'm talking about what is last what's last successful so when you
22:23
perform a task it creates a task instance which represents a single execution of that task which may run to completion it might fail with an exception it might be canceled it might possibly be canceled before it even has a chance to run and if you're using the drop modifier and it's these things
22:41
that actually expose the dot value the dot error rather than it being some sort of upper level global property on that on the task object so if you recall this example if you perform this a bunch of times you're going to be creating a bunch of task instances that belong to my task and dot value and
23:05
dot error exist on here and when you want to actually have access to those values because they're very useful for driving data in the template you basically have to say which one you actually want because there's multiple task instances they'll be created under a given task so in other words with
23:24
concurrency there isn't just one dot value there isn't just one attempt to load the data on the screen and there isn't one attempt to hit the server you have to sort of tell ember concurrency which is the one that you actually want and when you do you have the freedom to basically define how stale or how eager your your UIs are when you start reloading you get into
23:42
like reloading data so the top level tasks in this case ship widgets exposes properties to recently perform tasks instances one of them is last which is the most the one that you just performed which might still be running it might eventually run to completion or have an error last successful is the last one that ran to completion return to value last
24:03
error is the one that through an error which can be useful sometimes for displaying like error loading banners and some other things I don't expect you to really take very much away from this slide but just to make it clear these are the error these are sort of the there's last and last successful
24:20
and last error these are task instances that ship widgets the task will maintain a reference to and every task instance has a value an error is successful error so is this clown town is this have you flipped the bozo bit on what I'm saying am I really expecting to learn all this stuff well really I'm actually expecting you to maybe if you're interested learn two properties
24:42
on a task and a few properties on a task instance and mentally construct that matrix in your head of which piece of data you actually want but right I mean and it's worse that you end up with code that sort of looks like like this so why would you ever do that so come back to this old example I
25:00
didn't really show you the template code for this but just so you know have a sense of what this looks like in practice here's I guess here's what the here's here's the piece of code that actually exposes data to the template we say with submit form dot last successful value as result and then
25:21
we just you know loop over it and display all the stores and that's how this works and what we use last successful here but with just a slight tweak of the property that you use to drill down to the specific task instance whose whose values whose data you care about with just a slight tweak you can sort of change this UI from something that is always displaying data
25:43
even if it might be stale even if the user has already expressed interest in getting a more up-to-date version of that data you could just make one change you could replace last successful with last which this is the only thing that changed down here and then when you've already got
26:00
results then when you press the button again the results clear and you've basically chosen an API that is as fresh as possible that never wants to display stale data and this might seem like a minor thing but it's just it's one of these cases that were usually the API's play favorites they promise proxies you have to swap out the property which meant you
26:22
lost access to the old attempt to fetch data and it's just one of these like slight missteps that makes it really hard to for you to move between different styles of async data loading with any sort of like alacrity so it's really nice that all that you have to do is just change one property which
26:40
value do you want do you want the one that last completed or do you eagerly want the newest value even if it doesn't exist yet makes it really really easy and so really this just boils down to the fact that ember concurrency pays a lot of respect to the concept of essential state versus accidental state and these are terms that are sort of originated from a white paper from I
27:01
think 2006 called out of the tar pit and basically is a paper that talks about the common cases of complexity in that that come out of software and they sort of say that the root of all evil and the cause of a lot of complexity is so-called accidental state it's a state that you don't actually need to reconstruct you know the page that you're viewing or the
27:23
operations that you're doing it's just state that sort of got duplicated even though you've sort of expressed it elsewhere and could just re-derive it and just a very simple example is if for some reason you had a object in your code that was a user's array that had two elements in it but you also had a user account saying two you know you should wonder why this is
27:42
there why did I need to actually make this a piece of data that I may or may not have to update over time when it's just I can always just say users dot length why would you ever do that so that's a very simple example of accidental state and the antidote of accidental state is to use derived state which is a way of just recomputing the values that you need
28:01
based on this bare minimum essential state and in ember you probably have some experience with using derived state if you use computer properties so these these should be familiar concepts the only thing that's new about ember concurrency is that it pays due respect to derived state over time it
28:20
keeps just enough amount of information to make it really easy to do sort of comparisons has the data changed it's the data stale all these different things that are usually pretty hard in without something like ember concurrency usually requires a lot of manual state tracking which is really easy to get wrong in an async concurrent environment so in general this is just
28:43
the idea that you should prefer declarative api's over imperative api's because property mutations particularly when interleave with a bunch of async operations happening at the same time quickly leads to just a combinatoric unreasonable mess of code that is just going to be error prone to make
29:00
and it's really hard to change and evolve over time so as much as there's never going to be a silver bullet and ember concurrency definitely has its warts and its problems it's definitely worth taking some time to sort of think about these async problems using derived state and I'm hoping that I can get more people interested in because I I want ember concurrency to
29:22
give you even more than there already is so it takes practice to think in this way but I think it's worth the effort and I think it's also kind of exciting because embers concurrency is kind of the only thing like it I haven't seen anything like it there's a few there's actually a few copycats coming out there's a react concurrency I don't think I saw an actual angular
29:42
concurrency but I saw a article that is reimplementing that task function for putting for supplying a generator function that you know runs async logic and so I think people recognize that this is missing from other worlds and that we're kind of privileged in ember to have this so hopefully you might
30:01
get excited about this and talk through some of the stuff for me but so in conclusion ember is really just three things it's a powerful syntax for expressing async in a way that's cancelable it's a powerful declarative API for constraining concurrency and it's a ton of derived state that you can build really expressive UIs with without going down
30:21
to the path of mutating a bunch of properties and managing state over time so that's it thank you