Code Monkey home page Code Monkey logo

async-plus's Introduction

async+

Documentation Team Chat MIT License Continuous Integration Swift 5.5 Twitter


Async+ for Swift provides a simple chainable interface for your async and throwing code, similar to promises and futures. Have the best of both worlds: you can use the async solution built into the language, but keep all the useful features of promises.

✏️ Usage

Basic chaining operations are:

  • .then arranges blocks one after another, passing along any values
  • .recover recovers from a thrown error with a backup value (or block to run)
  • .catch catches any errors (and allows you to throw new ones for later catch blocks)
  • attempt { ... } kicks off a chain as in the example below:
attempt {
    return try await getThing()
}.recover {
    error in
    return try await backupGetThing(error)
}.then {
    thing in
    await thing.doYour()
}.catch {
    error in
    alert(error)
}

For comparison, if we tried to write the above flow without Async+ we'd get something like this:

Task.init {
    do {
        let thing: Thing
        do {
            thing = try await getThing()
        } catch {
            thing = try await backupGetThing(error)
        }
        await thing.doYour()
    } catch {
        error in
        alert(error)
    }
}

Async+ allows async and/or throwing code to remain unnested, modular, and concise. For a full list of operations see the documentation.

Want to still use chained code within a do/catch block, Task.init, or similar context? Easy: chains are fully interoperable with async and/or throwing contexts via the operations .async(), and .asyncThrows() at the end of the chain, for example:

let foo = await attempt{ ... }.then{ ... }.async() // non-throwing chain
let foo = try await attempt{ ... }.then{ ... }.asyncThrows() // throwing chain

If the chain doesn't throw you will not be able to call asyncThrows on it (it is a Guarantee<T> type rather than a Promise<T> type), and vice versa. Similarly, chains with potential for uncaught errors will raise an unused value warning at compilation time.

💾 Installation

Async+ can be installed with either SwiftPM or CocoaPods.

For SwiftPM, in Xcode go to <your project> -> <ProjectName> -> Package Dependencies -> "+" and enter: https://github.com/async-plus/async-plus.git

Or modify your Package.swift file:

dependencies: [
    .Package(url: "https://github.com/async-plus/async-plus.git", majorVersion: 1, minor: 1),
] 

For CocoaPods, in your Podfile:

target "Change Me!" do
  pod "AsyncPlus", "~> 1.1"
end

To use Async+ in a Swift file you must import AsyncPlus at the top of the file.

📘 Documentation

Getting Started

Operations

Using chains from async or throwing contexts

Motivation and common patterns

Cancellation

Migrating from PromiseKit

Frequently asked questions (FAQ)

🚀 Feedback and Contributing

This package is in its initial release: please provide feedback and suggestions in order to help shape the API, either by submitting an issue on Github or sending a message on Discord.

Special thanks to the developers of PromiseKit and mxcl for inspiring this work and promoting its development.

async-plus's People

Contributors

engine-turning avatar mlch911 avatar montaguegabe avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

async-plus's Issues

Give types better names

Feature for the next major release:

Calling something a Node is a little ambiguous - maybe ChainItem.

Additionally, GenericNodeFailableAsync should be called GenericPromise, and the same for all four derivatives of whether they fail and if they are async. I think this can make the library much easier to understand for users and contributors.

Catchable should be Thenable.

we should be able to do this.

attempt {
  // something
  return 0
}.catch { error in
  print(error)
}.then { value in  // here we got a error: Reference to member 'then' cannot be resolved without a contextual type
  print(value)
}

Cocoapods Support

Thanks for the work! Nice little QoL improvements for those of us embracing Swift's native async/await implementation 🙌🏻

However, a lot of us are still (at least partially) still using Cocoapods for dependency management. In an ideal world, we would just use SPM for everything - but there are a lot of libraries that either:

  1. Don't support it at all yet
  2. Support it, but lose some required features that Cocoapods provides (i.e. subspecs)

Could you integrate this project with pods so all the rest of us can easily import it? 😄

Should not allow catch on non-void chain

attempt {
    return 2
}.catch {
    err in 
    ...
}

^ should not be a valid pattern because the 2 goes unused in the catch block. I wish I could write where T != () - that would make thing much much easier to solve this without adding another bit of data to chain items.

AppKit is not available when building for iOS.

Using the library with SPM in project built for iOS in Xcode 13.3.
When trying to build the project it gives the error:

"AppKit is not available when building for iOS. Consider using #if targetEnvironment(macCatalyst) to conditionally import this framework when building for Mac Catalyst."

I can see the file Node is importing AppKit, is this intentional?

Add protocols for operations

A feature for the next release:

We should be able to write this code:

extension Catchable {
    func myCatchOperation() -> SomeComplexType {
        self.catch {
            err in 
            ...
        }
    }
}

..and have this extension apply to both Promises and synchronous AsyncPlus.Results, giving them both a myCatchOperation. The alternative is writing two separate extensions: one for a Promise and one for a Result, which is much easier to understand for the user of the package, but redundant.

Potential feature: get

In Swift, Task has an overloaded get that is throwing iff Failure is Never.

In the same way, we should probably combine .asyncThrows and .async and .value and .result into a single overloaded function called .get the result would be async and/or throwing depending on the underlying implementation. Then if the async/throwing status of a chain changes, you don't have to change the name of the thing that accesses (one fewer thing to change).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.