Skip to content

Instantly share code, notes, and snippets.

@dfkaye
Created February 4, 2022 23:05
Show Gist options
  • Save dfkaye/0f5a16b738a6d59847d84d24f6976523 to your computer and use it in GitHub Desktop.
Save dfkaye/0f5a16b738a6d59847d84d24f6976523 to your computer and use it in GitHub Desktop.
SAM pattern, loose example of pattern to click for data, show "loading" status, request data, handle data response, and update status again.

SAM looping example

Feb. 4, 2022

Response to https://gitter.im/jdubray/sam?at=61fd970e1fe6ba5a970c6dbd.

This is close to JavaScript with some pseudo-code steps to illustrate the click -> loadData (& setStatus) -> model update -> state update -> view render loop.

View:

<button> onclick: Action({ action: "loadRemoteData" });

Action:

loadRemoteData() {
  // propose new status
  Model({ step: "status", value: "loading" });
  
  // Make asynchronous request
  fetch(url)
    .then(res => res.json())
    .then(json => json.results)
    .then(results => {
      // Pass results to model.
      Model({ step: "update", value: results })
    });
}

Model

identifies the acceptor or step function and passes the value.

function Model({ step, value }) {
  
  // step/acceptor functions can be members of Model or private members of internal model API.
  
  Model[step](value);
}

The model's step/acceptor function(s) can guard against same step+value combinations.

function status(value) {
  /*
    So, if the call to Model({ step: "status", value: "loading" }) does not change
    the model's status (i.e., it's already "loading"), then the model can just return
    at this point and not notify the State.
   */
  if (model.status.value === value) {
    return;
  }

  // Otherwise go ahead and update...
  model.status.value = value;
  
  State(model);
}

As for updating the model data, you can mutate it all at once (or run it through normalizing, santizing, error-checking, etc.) and set the status directly.

function update(value) {
  model = Object.assign(model, { data: value }, { status: "done" });
  
  State(model);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment