{"id":18962272,"url":"https://github.com/lipp/lua-step","last_synced_at":"2026-04-02T01:30:17.721Z","repository":{"id":7945706,"uuid":"9339271","full_name":"lipp/lua-step","owner":"lipp","description":"Un-nest asynchronous control flow.","archived":false,"fork":false,"pushed_at":"2013-06-10T09:45:46.000Z","size":172,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-01-01T05:16:57.581Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Lua","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lipp.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2013-04-10T05:58:53.000Z","updated_at":"2021-04-16T06:56:57.000Z","dependencies_parsed_at":"2022-07-12T15:03:10.628Z","dependency_job_id":null,"html_url":"https://github.com/lipp/lua-step","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lipp%2Flua-step","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lipp%2Flua-step/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lipp%2Flua-step/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lipp%2Flua-step/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lipp","download_url":"https://codeload.github.com/lipp/lua-step/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":239958310,"owners_count":19724926,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-08T14:15:48.390Z","updated_at":"2026-04-02T01:30:17.633Z","avatar_url":"https://github.com/lipp.png","language":"Lua","funding_links":[],"categories":[],"sub_categories":[],"readme":"# About\n\nUn-nest asynchronous control flow.\n\n# Installation\n\n    $ git clone https://github.com/lipp/lua-step.git\n    $ cd lua-step\n    $ sudo luarocks make\n\n# Build status\n\n[![Build Status](https://travis-ci.org/lipp/lua-step.png?branch=master)](https://travis-ci.org/lipp/lua-step/builds)\n\n# Wrap up\n\n```lua\n\nlocal step = require'step'\n\nlocal some_async_action = step.new({\n  try = {\n    [1] = function(step)\n      -- do some async stuff\n      ...\n      -- the first argument to all try functions\n      -- is the step table\n      step.success(123,'abc')\n    end,\n    [2] = function(step,num,str)\n      -- arguments to step.success are forwarded to the \n      -- next function in try list.\n      -- so num==123 and str=='abc' \n      -- do some more async stuff\n      ...\n      step.success({1,2,3})\n    end,\n    [3] = function(step,array)\n      if array[2] == 78 then\n        step.success()\n      else\n        step.error('something went wrong')\n      end\n    end,\n  },\n  catch = function(err)\n    -- catch will be called when step.error has been called\n    -- or if some error happened (is thrown).\n    -- no further try step will be executed.\n    print('ERROR',err)\n  end,\n  finally = function()\n    -- finally is called in any case\n    cleanup_some_stuff()\n  end\n})\n\nsome_async_action()\n```\n\n# API\n\n## The step table (module)\n\n### step.new (function)\n\nCreates a step instance and returns a function which starts execution. Argument `arg` is a table with the following fields:\n\n#### arg.try\n\nAn array of functions which should be executed.\n\n#### arg.catch\n\nA function which is called on error, optional.\n\n### arg.finally\n\nA function which is executed either after last try finished or after catch was invoked in casew of error, optional\n\n\n## The step table (passed to callbacks)\n\n### step.success (function)\n\nProgresses with the next `try` entry or with `finally` if it was the last `try` entry.\nAll arguments are forwarded to the respective function as additional function arguments.\n\n### step.error (function)\n\nProgresses with the `catch` function and passes the `err` as additional argument to `catch`.\nAfter `catch` has been called, `finally` will be called.\n\n### step.result (array)\n\nArray (table), which holds all results (arguments which have been passed to step.success) for each `try` entry.\n\n### step.index (number)\n\nThe currently executed function index inside the `try` array. Useful to manipulate `step.try` at runtime.\n\n### step.try (array)\n\nArray of functions. Try steps can be inserted at runtime, using this array and `step.index`.\n\n```lua\nlocal async_op = step.new({\n  try = {\n\t...\n    function(step)\n\t  -- insert a try step on-the-fly right\n\t  -- after this step.\n\t  table.insert(step.try,step.index+1,function(step)\n\t    ...\n\t  end)\n\tend,\n    ...\n  }\n})\n```\n\n### step.context (table)\n\nA table which can be freely used to store context between `try` entries and/or `finally` call. Useful for doing cleanup\ncode in finally, e.g.:\n\n```lua\nlocal async_op = step.new({\n  try = {\n    [1] = function(step)\n\t  ...\n\tend,\n    ...\n    [3] = function(step)\n\t  step.context.file = io.open('foo.txt')\n\tend,\n\t...\n  },\n  finally = function(step)\n    if step.context.file then\n\t  step.context.file:close()\n    end\n  end\n})\n```\n\n# Examples\n\nSee `spec` folder with [busted](https://github.com/Olivine-Labs/busted) tests and `examples` folder for more\nexamples.\n\n# Motivation\n\nAs asynchronous control flow gets more complex readability suffers\ngreatly. Often the code for a \"simple\" synchronous sequence of operations got\ndeeply nested in async programming:\n\n```lua\n--------------------\n-- sync flow\n--------------------\nlocal ok,err = pcall(function()\n  a()\n  b()\n  c()\n  print('yup')\nend)\n\nif ok then\n  ...\nelse\n  ...\nend\n\n--------------------\n-- becomes\n--------------------\nlocal on_error = function() ... end\n\na({\n  success = function()\n    b({\n      success = function()\n        c({\n          success = function()\n            print('yup')\n          end,\n          error = on_error\n        })\n      end,\n      error = on_error\n    })\n  end,\n  error = on_error\n})\n```\n\nWorse, if results or state has to be shared between `a`,`b` and `c`\nlots up upvalues are required. A comparison of programming async with\nand without lua-step can be found in the `example` folder.\n\nMoreover, programmatically executing async execution steps is hardly possible\nwithout (a mechanism similar to) lua-step.\n\n```lua\n--------------------\n-- sync flow\n--------------------\nlocal exec_steps = read_config()\n\nlocal ok,err = pcall(function()\n  for _,exec_step in ipairs(exec_steps) do\n    exec_step()\n  end\nend\n\nif not ok then\n  ...\nend\n\ncleanup()\n\n--------------------\n-- becomse without lua-step\n--------------------\n\n-- ???\n-- ???\n-- ???\n\n--------------------\n-- becomse with lua-step\n--------------------\nlocal async_exec_steps = read_config()\n\nlocal try = async_exec_steps\n\nlocal exec_all_async_steps = step.new({\n  try = async_exec_steps,\n  catch = on_error,\n  finally = cleanup\n})\n\nexec_all_async_steps()\n```\n\nlua-step tries to improve readibility and maintainablity of async\ncontrol flows.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flipp%2Flua-step","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flipp%2Flua-step","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flipp%2Flua-step/lists"}