{"id":18616528,"url":"https://github.com/davidask/futures","last_synced_at":"2025-04-11T01:31:49.545Z","repository":{"id":63907689,"uuid":"134900190","full_name":"davidask/Futures","owner":"davidask","description":"Lightweight promises for iOS, macOS, tvOS, watchOS, and Linux","archived":false,"fork":false,"pushed_at":"2020-06-11T20:38:02.000Z","size":1729,"stargazers_count":57,"open_issues_count":0,"forks_count":5,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-08-04T11:02:02.504Z","etag":null,"topics":["async","futures","ios","macos","promises","server-side-swift","swift","tvos","watchos"],"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/davidask.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":"2018-05-25T20:08:36.000Z","updated_at":"2024-08-04T11:02:02.505Z","dependencies_parsed_at":"2022-11-28T22:54:41.844Z","dependency_job_id":null,"html_url":"https://github.com/davidask/Futures","commit_stats":null,"previous_names":["formbound/futures"],"tags_count":13,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidask%2FFutures","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidask%2FFutures/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidask%2FFutures/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidask%2FFutures/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/davidask","download_url":"https://codeload.github.com/davidask/Futures/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248325244,"owners_count":21084896,"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","futures","ios","macos","promises","server-side-swift","swift","tvos","watchos"],"created_at":"2024-11-07T03:35:34.838Z","updated_at":"2025-04-11T01:31:46.842Z","avatar_url":"https://github.com/davidask.png","language":"Swift","readme":"# Futures\n![Tests](https://github.com/davidask/Futures/workflows/Tests/badge.svg)\n\nFutures is a cross-platform framework for simplifying asynchronous programming, written in Swift. It's lightweight, fast, and easy to understand.\n\n### Supported Platforms\n\n* Ubuntu 14.04\n* macOS 10.9\n* tvOS 9.0\n* iOS 8.0\n* watchOS 2.0\n\n\n### Architecture\n\nFundamentally, Futures is a very simple framework, that consists of two types:\n\n* `Promise`, a single assignment container producing a `Future`\n* `Future`, a read-only container resolving into either a value, or an error\n\n\nIn many promise frameworks, a promise is undistinguished from a future. This introduces mutability of a promise that gets passed around. In Futures, a `Future` is the observable value while a `Promise` is the function that sets the value.\n\n\nFutures are observed, by default, on a single concurrent dispatch queue. This queue can be modified by assigning a different queue to `DispatchQueue.futures`. You can also specify a queue of your choice to each callback added to a future .\n\n\nA future is regarded as:\n\n* `resolved`, if its value is set\n* `fulfilled`, if the value is set, and successful\n* `rejected`, if the value is set, and a failure (error)\n\n\n## Usage\n\nWhen a function returns a `Future\u003cValue\u003e`, you can either decide to observe it directly, or continue with more asynchronous tasks. For observing, you use:\n\n* `whenResolved`, if you're interested in both a value and a rejection error \n* `whenFulfilled`, if you only care about the values\n* `whenRejected`, if you only care about the error\n\n\nIf you have more asynchronous work to do based on the result of the first future, you can use\n\n* `flatMap()`, to execute another future based on the result of the current one\n* `flatMapIfRejected()`, to recover from a potential error resulting from the current future\n* `flatMapThrowing()`, to transform the fulfilled value of the current future or return a rejected future\n* `map()`, to transform the fulfilled value of the current future\n* `recover()`,to transform a rejected future into a fulfilled future\n* `always()`, to execute a `Void` returning closure regardless of whether the current future is rejected or resolved\n* `and()`, to combine the result of two futures into a single tuple\n* `Future\u003cT\u003e.reduce()`, to combine the result of multiple futures into a single future\n\n\nNote that you can specify an observation dispatch queue for all these functions. For instance, you can use `flatMap(on: .main)`, or `.map(on: .global())`. By default, the queue is `DispatchQueue.futures`.\n\nAs a simple example, this is how some code may look:\n\n```swift\nlet future = loadNetworkResource(\n    from: URL(\"http://someHost/resource\")!\n).flatMapThrowing { data in\n    try jsonDecoder.decode(SomeType.self, from: data)\n}.always {\n    someFunctionToExecuteRegardless()\n}\n\nfuture.whenFulfilled(on: .main) { someType in\n    // Success\n}\n\nfuture.whenRejected(on: .main) { error in\n    // Error\n}\n```\n\nTo create your functions returning a `Future\u003cT\u003e`, you create a new pending promise, and resolve it when appropriate.\n\n```swift\nfunc performAsynchronousWork() -\u003e Future\u003cString\u003e {\n    let promise = Promise\u003cString\u003e()\n\n    DispatchQueue.global().async {\n        promise.fulfill(someString)\n\n        // If error\n        promise.reject(error)\n    }\n\n    return promise.future\n}\n```\n\nYou can also use shorthands.\n\n```swift\npromise {\n     try jsonDecoder.decode(SomeType.self, from: data)\n} // Future\u003cSomeType\u003e\n```\n\nOr shorthands which you can return from asynchronously.\n```swift\npromise(String.self) { completion in\n    /// ... on success ...\n    completion(.fulfill(\"Some string\"))\n    /// ... if error ...\n    completion(.reject(anError))\n} // Future\u003cString\u003e\n```\n\n\n## Documentation\n\nThe complete documentation can be found [here](https://davidask.github.io/Futures/).\n\n## Getting started\n\nFutures can be added to your project either using [Carthage](https://github.com/Carthage/Carthage) or Swift package manager.\n\n\nIf you want to depend on Futures in your project, it's as simple as adding a `dependencies` clause to your `Package.swift`:\n\n```swift\ndependencies: [\n    .package(url: \"https://github.com/davidask/Futures.git\", from: \"1.6.0\")\n]\n```\n\nOr, add a dependency in your `Cartfile`:\n\n```\ngithub \"davidask/Futures\"\n```\n\nMore details on using Carthage can be found [here](https://github.com/Carthage/Carthage#quick-start).\n\nLastly, import the module in your Swift files\n\n```swift\nimport Futures\n```\n\n## Contribute\nPlease feel welcome contributing to **Futures**, check the ``LICENSE`` file for more info.\n\n## Credits\n\nDavid Ask","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdavidask%2Ffutures","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdavidask%2Ffutures","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdavidask%2Ffutures/lists"}