{"id":20440357,"url":"https://github.com/smakeev/asyncswift","last_synced_at":"2026-03-16T07:03:07.452Z","repository":{"id":62455793,"uuid":"225080037","full_name":"smakeev/AsyncSwift","owner":"smakeev","description":"Swift, Future, Async, Await.","archived":false,"fork":false,"pushed_at":"2020-11-25T15:49:31.000Z","size":75,"stargazers_count":6,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-26T17:11:21.208Z","etag":null,"topics":["async","async-await","await","future","swift5"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/smakeev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-11-30T22:55:51.000Z","updated_at":"2021-09-14T10:15:30.000Z","dependencies_parsed_at":"2022-11-02T00:01:16.369Z","dependency_job_id":null,"html_url":"https://github.com/smakeev/AsyncSwift","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smakeev%2FAsyncSwift","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smakeev%2FAsyncSwift/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smakeev%2FAsyncSwift/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smakeev%2FAsyncSwift/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/smakeev","download_url":"https://codeload.github.com/smakeev/AsyncSwift/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248643004,"owners_count":21138355,"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":["async","async-await","await","future","swift5"],"created_at":"2024-11-15T09:23:49.901Z","updated_at":"2026-03-16T07:03:02.408Z","avatar_url":"https://github.com/smakeev.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# AsyncSwift\n\nFramework for async tasks in Swift using futures and async-await syntax.\n\n## How to use:\n1) You may get the source directly.\n2) Using cocoa pods\n\t```\n\tpod \"SomeAsyncSwift\"\t\n\t```\n\tand in your swift files:\n\t```swift\n\timport SomeAsyncSwift\n\t```\n\n## Asynchronous programming: futures, async, await\n\nAsynchronous operations let your program complete work while waiting for another operation to finish. Here are some common asynchronous operations:\n  * Fetching data over a network.\n  * Writing to a database.\n  * Reading data from a file.\n  \nAsyncSwift allows you to use ```AsyncAwaitFuture``` class and ```async``` ```await``` keywords.\n\nFor simplicity ```AsyncAwaitFuture``` has a simple name ```AFuture```\n\n# ```AFuture```\n\n```AFuture``` is a generic class with parameter ```result``` of a generic type.\n```AFuture\u003cVoid\u003e``` could be called as ```SomeFuture```\n\nFuture is an instance of ```AFuture``` class with some result type.\nA future represents the result of an asynchronous operation, and can have two states: ```resolved == true``` , ```resolved == false```\nAlso it provides substate ```hasError``` due to future could be resolved not only with success but also woth error.\n\nIn case of resolved future can provide the result.\n```result``` property is a read only property of generic type, and it can be nil.\nFuture could be resolved with ```nil``` result. This does not mean somthing is wrong. \nSo to determine if future is resolved you should check ```resolved``` property.\nIn case of error ```resolved``` property shows ```true``` but also ```hasError``` property shows ```true```\nExactly error could be found in ```Error``` property. It has an ```Any?``` type and could be nil.\n\n\n# Examples:\n```swift\n    let future1 = SomeFuture.delay(3)\n```\n  Here ```future1``` is a ```AsyncAwaitFuture\u003cVoid\u003e``` and it will be resolved after 3 seconds.\n  \n  ```swift\n  \tlet future2: AFuture\u003cInt\u003e = async {\n\t\tfor _ in 1...1000000 {\n\t\t\t//do something\n\t\t}\n\t\treturn 10 //resolve with 10\n\t}\n  ```\n  \n  The special constraction ```async``` returns a future. Will be described in details later.\n  \n  here ```future2``` is a ```AsyncAwaitFuture\u003cInt\u003e``` and it will be resolved with 10 after the cicle finished.\n  \n  ```swift\n    let future3 = SomeFuture.wait([future1, future2])\n  ```\n  \n  Here ```future3``` is a ```AsyncAwaitFuture\u003cVoid\u003e``` and it will be resolved after ```future1``` and ```future2``` be resolved.\n  \n  To wait for ```future1``` and ```future2``` you could use ```await``` keyword wich is just a function in this realization.\n  \n  ```swift\n  try! await(SomeFuture.wait([future1, future2]))\n  ```\n  \n  In this case your current thread will be waiting for ```future1``` and ```future2```\n  \n  \n  # Working with futures: async and await\n  \n  The ```async``` and ```await``` keywords provide a declarative way to define asynchronous functions and use their results. \n  \n  If the function has a declared return type, then update the type to be ```AFuture\u003cT\u003e```, where T is the type of the value that the function returns. If the function doesn’t explicitly return a value, then the return type is ```AFuture\u003cvoid\u003e``` or ```SomeFuture```\n  The function should use ```async``` keyword inside it's body:\n  \n  ```swift\n  func f0() -\u003e AFuture\u003cInt\u003e {\n\tasync {\n\t\tsleep(2) //to imitate some work in BG.\n\t\treturn 1\n\t}\n}\n  ```\n  \n  This function could have parameters:\n  \n  ```swift\n    func f1(_ a: Int) -\u003e AFuture\u003cInt\u003e {\n    \tasync {\n\t\tsleep(2)\n\t\treturn a\n       }\n    }\n  ```\n  For such functions you may directly use ```await``` to make your code wait future to be resolved\n  ```swift\n\tlet result = try! await(f1(5))\n  ```\n  \n  You may use functions to obtain futures and observe it's states.\n  To bserve future states you may use several ways:\n  \n  ```onSuccess``` method. It will be called after the future been resolved.\n  If call ```onSuccess``` to resolved future, it will be called immediately.\n  \n```swift\n future.onResolved { result in\n\tprint(\" Future resolved with:\\(result)\")\n}\n```\n  \n  ```then``` is close to ```onSuccess``` but returns the future wich waits for first future been resolved.\n  This allows you to create future's chain\n  Then has an argument of type which it will embade to it's future.\n  \n```swift\nlet future = findEntryPoint().then(EntryPoint.self) { entryPoint in\n\tguard let validEntryPoint = entryPoint else { fatalError()}\n\treturn self.runFromEnryPoint(validEntryPoint)\n}.then(Void.self, finishChainWithOptinalParameter)\n```\n In this example all functions return future objects, so are async functions.\n \n ```always``` is close to ```onSuccess``` but also works in case of errors. \n \n The last example could be recreated with ```async await``` constractions\n```swift\n \t  let entryPoint = await(findEntryPoint())\n\t\tguard let validEntryPoint = entryPoint else { fatalError() /*to test exceptions*/}\n\t\tlet result = await(self.runFromEnryPoint(validEntryPoint))\n```\n \n If you don't whant your thread to be waiting in ```await``` make sure you call it inside ```async```\n ```async``` will return future you may subscribe on.\n \n \n ## note: future does not keep ref. to itself. It means you should always keep ref.to future before it finished it's work.\n \n \n# ```await```\n\n```await``` is a function wich makes your current thread be waiting for future been resolved.\nIt throws an AFutureErrors.FutureError if future has been resolved with an error.\n\nIn case of using functions not returning future you may use ```await``` variants which takes arguments and function.\nit takes arguments (from 0 up to 10)* and a function not returning ```AFuture``` and produces an ```AFuture\u003cType\u003e``` where ```Type``` is your function return type.\n \n* if you need more then 10 arguments you need create ```await``` yourself.\n \n # Handling errors:\n \n ## How to produce error:\nFuture can produce an error in case of it's async function throws an exception\n\t\n```swift\nlet future: AFuture\u003cInt\u003e = async {\n\tfor i in 1...1000000 {\n\t\tif i == 10000 {\n\t\t\tthrow(TestErrors.testExcepton(howMany: i))\n\t\t}\n\t}\n\treturn 10\n}\n```  \nIn this example future will not return 10. Instead it will have an error of type ```TestErrors```\nHere is error type:\n```swift\n\tenum TestErrors: Error {\n\t\tcase testExcepton(howMany: Int)\n\t}\n```\n  \n## How to handle errors in future:\n\n```await``` throws in case of error in future.\nSo the first way is regular exceptions handling. \n\nBut you may use ```try!``` before ```Future.wait``` due to it never thows.\n\nTake a look at this example:\n\n```swift\nfunc testException() {\n\tlet future: AFuture\u003cInt\u003e = async {\n\t\tfor i in 1...1000000 {\n\t\t\tif i == 10000 {\n\t\t\t\tthrow(TestErrors.testExcepton(howMany: i))\n\t\t\t}\n\t\t}\n\t\treturn 10\n\t}\n\t\n\ttry! await(SomeFuture.wait([future]))\n\tXCTAssert(future.resolved)\n\tXCTAssert(future.hasError)\n\tlet error = future.error\n\tif let validError = error as? TestErrors {\n\t\tswitch validError {\n\t\tcase .testExcepton(let howMany): XCTAssert(howMany == 10000)\n\t\t}\n\t} else {\n\t\tXCTAssert(false)\n\t}\n}\n```\nSo as you can see ```SomeFuture.wait([future])``` works as if future has been resolved with value.\nBut it will have an error instead.\n\nYou also may use ```onError``` handler.\nIt works in the same way as ```onSuccess``` but in case of error.\n\nIf you want to fix the problem use ```catchError```\n\nExample of future chaining:\n```swift\nfunc testChain() {\n\tvar gotThenBlock = false\n\tvar wasInThen    = false\n\tvar wasInAlways  = false\n\tlet future: AFuture\u003cString\u003e = async { () -\u003e Int in\n\t\tfor i in 1...1000000 {\n\t\t\tif i == 10000 {\n\t\t\t\tthrow(TestErrors.testExcepton(howMany: i))\n\t\t\t}\n\t\t}\n\t\treturn 10\n\t}.then(String.self) { result in\n\t\tgotThenBlock = true\n\t\treturn async {\n\t\t\twasInThen = true\n\t\t\treturn \"Ten\"\n\t\t}\n\t}.catchError { _ in\n\t\treturn \"10000\"\n\t}.always {\n\t\twasInAlways = true\n\t}\n\n\tlet result = await(future)\n\tXCTAssert(result == \"10000\")\n\tXCTAssert(wasInAlways)\n\tXCTAssert(!gotThenBlock)\n\tXCTAssert(!wasInThen)\n}\n```\n\nIn this test we have the first future provides ```Int``` result and next future provides ```String```\nBut the first future provides an error. We catch it by ```catchError``` and provides fixed value here.\nNote: ```catchError``` is a new future itself. It means it also could have ```then``` and could provides error.\nSo you could have several ```catchError```s one after another. \n\n```Always``` will be called in any case.\n\n## Handling errors in ```await```\n\n1st variant is to use standard ```try-catch``` as ```await``` trhows in case of ```Future``` has an error.\n\nDue to ```await``` takes ```AFuture``` you may produce ```catchError``` to the future\nIf ```catchError``` produces the value always you may just use ```try!```\nThis is not recommended way due to ```catchError``` may also returns an error.\nHere this is done for simplicity.\n\n```swift\nfunc testExceptionsInAwait() {\n\tlet future: AFuture\u003cInt\u003e = async {\n\t\tfor i in 1...1000000 {\n\t\t\tif i == 10000 {\n\t\t\t\tthrow(TestErrors.testExcepton(howMany: i))\n\t\t\t}\n\t\t}\n\t\treturn 10\n\t}\n\tlet result = try! await(future.catchError { error in\n\t\tif let validError = error as? TestErrors {\n\t\t\tswitch validError {\n\t\t\tcase .testExcepton(let howMany): XCTAssert(howMany == 10000)\n\t\t\t}\n\t\t} else {\n\t\t\tXCTAssert(false)\n\t\t}\n\t\t\n\t\treturn 20\n\t})\n\t\n\tXCTAssert(result == 20)\n}\n```\n\nIf you use ```await``` to function wich does not provide future you don't have such oportunity but first way ```try-catch``` is awailable.\n\n## Streams and Async observable properties \n\nTake a look at `AsyncObservablesTests` and `StreamTests` for examples.\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsmakeev%2Fasyncswift","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsmakeev%2Fasyncswift","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsmakeev%2Fasyncswift/lists"}