Promises simplify asynchronous programming, freeing you up to focus on the more important things

Related tags

Event swift promises objc
Overview

PromiseKit

badge-pod badge-languages badge-pms badge-platforms badge-travis


Promises simplify asynchronous programming, freeing you up to focus on the more important things. They are easy to learn, easy to master and result in clearer, more readable code. Your co-workers will thank you.

UIApplication.shared.isNetworkActivityIndicatorVisible = true

let fetchImage = URLSession.shared.dataTask(.promise, with: url).compactMap{ UIImage(data: $0.data) }
let fetchLocation = CLLocationManager.requestLocation().lastValue

firstly {
    when(fulfilled: fetchImage, fetchLocation)
}.done { image, location in
    self.imageView.image = image
    self.label.text = "\(location)"
}.ensure {
    UIApplication.shared.isNetworkActivityIndicatorVisible = false
}.catch { error in
    self.show(UIAlertController(for: error), sender: self)
}

PromiseKit is a thoughtful and complete implementation of promises for any platform that has a swiftc. It has excellent Objective-C bridging and delightful specializations for iOS, macOS, tvOS and watchOS. It is a top-100 pod used in many of the most popular apps in the world.

codecov

PromiseKit 7 Alpha

We are testing PromiseKit 7 alpha, it is Swift 5 only. It is tagged and thus importable in all package managers.

PromiseKit 6

Release notes and migration guide.

Quick Start

In your Podfile:

6.8" end ">
use_frameworks!

target "Change Me!" do
  pod "PromiseKit", "~> 6.8"
end

The above gives an Xcode warning? See our Installation Guide.

PromiseKit 6, 5 and 4 support Xcode 8.3, 9.x and 10.0; Swift 3.1, 3.2, 3.3, 3.4, 4.0, 4.1, 4.2, 4.3 and 5.0 (development snapshots); iOS, macOS, tvOS, watchOS, Linux and Android; CocoaPods, Carthage and SwiftPM; (CI Matrix).

For Carthage, SwiftPM, Accio, etc., or for instructions when using older Swifts or Xcodes, see our Installation Guide. We recommend Carthage or Accio.

Professionally Supported PromiseKit is Now Available

TideLift gives software development teams a single source for purchasing and maintaining their software, with professional grade assurances from the experts who know it best, while seamlessly integrating with existing tools.

Get Professional Support for PromiseKit with TideLift.

PromiseKit is Thousands of Hours of Work

Hey there, I’m Max Howell. I’m a prolific producer of open source software and probably you already use some of it (I created brew). I work full-time on open source and it’s hard; currently I earn less than minimum wage. Please help me continue my work, I appreciate it 🙏🏻

Other ways to say thanks.

Documentation

Extensions

Promises are only as useful as the asynchronous tasks they represent. Thus, we have converted (almost) all of Apple’s APIs to promises. The default CocoaPod provides Promises and the extensions for Foundation and UIKit. The other extensions are available by specifying additional subspecs in your Podfile, e.g.:

pod "PromiseKit/MapKit"          # MKDirections().calculate().then { /*…*/ }
pod "PromiseKit/CoreLocation"    # CLLocationManager.requestLocation().then { /*…*/ }

All our extensions are separate repositories at the PromiseKit organization.

I don't want the extensions!

Then don’t have them:

6.8" ">
pod "PromiseKit/CorePromise", "~> 6.8"

Note: Carthage installations come with no extensions by default.

Choose Your Networking Library

Promise chains commonly start with a network operation. Thus, we offer extensions for URLSession:

// pod 'PromiseKit/Foundation'  # https://github.com/PromiseKit/Foundation

firstly {
    URLSession.shared.dataTask(.promise, with: try makeUrlRequest()).validate()
    // ^^ we provide `.validate()` so that eg. 404s get converted to errors
}.map {
    try JSONDecoder().decode(Foo.self, with: $0.data)
}.done { foo in
    //
}.catch { error in
    //
}

func makeUrlRequest() throws -> URLRequest {
    var rq = URLRequest(url: url)
    rq.httpMethod = "POST"
    rq.addValue("application/json", forHTTPHeaderField: "Content-Type")
    rq.addValue("application/json", forHTTPHeaderField: "Accept")
    rq.httpBody = try JSONEncoder().encode(obj)
    return rq
}

And Alamofire:

// pod 'PromiseKit/Alamofire'  # https://github.com/PromiseKit/Alamofire-

firstly {
    Alamofire
        .request("http://example.com", method: .post, parameters: params)
        .responseDecodable(Foo.self)
}.done { foo in
    //
}.catch { error in
    //
}

Nowadays, considering that:

  • We almost always POST JSON
  • We now have JSONDecoder
  • PromiseKit now has map and other functional primitives
  • PromiseKit (like Alamofire, but not raw-URLSession) also defaults to having callbacks go to the main thread

We recommend vanilla URLSession. It uses fewer black boxes and sticks closer to the metal. Alamofire was essential until the three bullet points above became true, but nowadays it isn’t really necessary.

Support

Please check our Troubleshooting Guide, and if after that you still have a question, ask at our Gitter chat channel or on our bug tracker.

Security & Vulnerability Reporting or Disclosure

https://tidelift.com/security

Comments
  • Restrict Choices for Encrypter's Ciphers

    Restrict Choices for Encrypter's Ciphers

    Currently, the encrypter class lets you select broken ciphers. I propose restricting the ciphers you're allowed to select. If a broken cipher is selected, an \InvalidArgumentException should be thrown.

    enhancement 
    opened by davidbyoung 18
  • Publish a coding standards document

    Publish a coding standards document

    Hi, great project.

    Your code is very consistent but doesn't always match Symfony / PSR style. For example: Use of double quotes instead of single quotes even though there is no "$var" inside the string, single line PHPDoc comments for class properties, ...

    It would be nice if you could publish a document explaining what style you expect contributors to adhere to.

    Bonus points if I could import it into PHPStorm.

    Thanks.

    screenshot from 2017-01-10 11-06-58

    enhancement 
    opened by connerbw 16
  • [FEATURE] QueryBuilder::whereIn

    [FEATURE] QueryBuilder::whereIn

    It would be nice if the query builder supported a whereIn function, along with orWhereIn. This is something I miss quite often also in other frameworks.

    Example usage:

    use Opulence\QueryBuilders\PostgreSql\QueryBuilder;
    
    $query = (new QueryBuilder)->select("id", "name", "email")
        ->from("users")
        ->whereIn("id", [1, 2, 3])
        ->orWhereIn("email", ["[email protected]", "[email protected]"]);
    echo $query->getSql();
    

    This would output:

    SELECT id, name, email FROM users WHERE id IN (?, ?, ?) OR email IN (?, ?)
    

    I wouldn't mind giving implementing this a shot, the only question is whether this should default to using named or unnamed parameters. Perhaps it could default to unnamed, with an optional parameter to use named parameters? I'd like to hear what you think.

    opened by MaartenStaa 15
  • phpDocumentor problem

    phpDocumentor problem

    Nice framework but unfortunately phpDocumentor does not read the IO\Stream folder probably because Opulence uses reserved names or because it does not support: void as return value.

    Unfortunately I do not know the reason.

    Could you resolve please?

    Thank you

    wontfix 
    opened by adrix71 12
  • Migration errors

    Migration errors

    While developing AbterPHP, I ran the migrations hundreds of times and it kept bugging me to debug query errors, because currently the migration commands wouldn't even tell me that there was an error. With these changes I would be able to create a migration class like this:

    <?php
    
    declare(strict_types=1);
    
    namespace AbterPhp\Framework\Databases\Migrations;
    
    use Opulence\Databases\Migrations\Migration;
    
    class BaseMigration extends Migration
    {
        // ...
    
        /**
         * @inheritdoc
         */
        public function down(): bool
        {
            $sql       = 'SELECT 1';
            $statement = $this->connection->prepare($sql);
            if (!$statement->execute()) {
                $this->errors = $statement->errorInfo();
    
                return false;
            }
    
            return true;
        }
    
        /**
         * @inheritdoc
         */
        public function up(): bool
        {
            $sql       = 'SELECT 1';
            $statement = $this->connection->prepare($sql);
            if (!$statement->execute()) {
                $this->errors = $statement->errorInfo();
    
                return false;
            }
    
            return true;
        }
    }
    

    Obviously this change would warrant at least a minor version bump, if not a major one.

    opened by peteraba 11
  • Environment setup is extremely confusing.

    Environment setup is extremely confusing.

    The entire environment setup is quite confusing to use. While it is possible to integrate it with other tools such as phinx, it isn't easy nor convenient.

    Dotenv is a fantastic package maintained by Vance that provides a seamless environment configuration experience. Simple to use and share between tooling.

    Could a move to using Dotenv be considered? Taking advantage of it will provide the best experience to developers.

    opened by Garbee 8
  • Initial efforts for PHP8 support

    Initial efforts for PHP8 support

    There are two main topics to be solved:

    1. Some PDO adapters are not compatible with \PDO classes they extend (Connection, Statement)
    2. Reflection usage. Especially relying on the now deprecated ReflectionParameter::getClass. Additionally it seems like something has changed in regards to tokenization / autoloader, because the ReflectionClass constructor fails for the parsed migrations in FileMigrationFinder
    opened by peteraba 7
  • unambiguous migration ordering during running migrations:down

    unambiguous migration ordering during running migrations:down

    Issue description

    The executedmigrations table will contain the datetime of the execution in the daterun column and this would be then used for finding the latest executed migration if you ran ./apex migrations:down. The problem is, if you ran previous migrations at once before, this will not provide a sufficient way to select the latest migration run. Instead it will pick a random one executed in the exact second of the truly last executed one.

    Example

    Code

    namespace AbterPhp\Users\Databases\Migrations;
    // ...
    class Init extends Migration
    {
        // ...
        public static function getCreationDate(): DateTime
        {
            return DateTime::createFromFormat(DateTime::ATOM, '2019-02-28T21:00:00+00:00');
        }
        // ...
    }
    
    namespace AbterPhp\Pages\Databases\Migrations;
    // ...
    class Init extends Migration
    {
        // ...
        public static function getCreationDate(): DateTime
        {
            return DateTime::createFromFormat(DateTime::ATOM, '2019-02-28T21:01:00+00:00');
        }
        // ...
    }
    
    namespace AbterPhp\Files\Databases\Migrations;
    // ...
    class Init extends Migration
    {
        // ...
        public static function getCreationDate(): DateTime
        {
            return DateTime::createFromFormat(DateTime::ATOM, '2019-02-28T22:00:00+00:00');
        }
        // ...
    }
    
    namespace AbterPhp\Contact\Databases\Migrations;
    // ...
    class Init extends Migration
    {
        // ...
        public static function getCreationDate(): DateTime
        {
            return DateTime::createFromFormat(DateTime::ATOM, '2019-02-28T23:00:00+00:00');
        }
        // ...
    }
    

    Database

    | migration | daterun | --------------| -----------| AbterPhp\Users\Databases\Migrations\Init | 2019-03-04 12:03:43 | AbterPhp\Contact\Databases\Migrations\Init | 2019-03-04 12:03:44 | AbterPhp\Files\Databases\Migrations\Init | 2019-03-04 12:03:44 | AbterPhp\Pages\Databases\Migrations\Init | 2019-03-04 12:03:44 |

    It may any of the last 3 for migrate:down.

    Incomplete list of potential fixes

    1. Replace daterun column with a time format which will contain some high resolution time. (Backwards compatible, but requires a schema upgrade)
    2. Store the getCreationDate in a column and use that as a second sorting parameter when selecting the "last run" migration.
    3. Retrieve all migrations run at the same time as the "last" one and select the migration with the latest getCreationDate returned. (Backwards compatible and no schema upgrade necessary, but he query will be somewhat harder to understand, and could lead to problems if someone changes the getCreatedAt value of a migration.)
    4. ~~Sleep 1 second before executing consecutive schema upgrades.~~ :smile:

    Note: Using microseconds as high resolution time is probably enough in most cases although it might just make it harder to reproduce the issue. Giving an option to use hrtime instead could have benefits, but only doable in PHP at the moment afaik. (https://pecl.php.net/package/hrtime, http://php.net/manual/en/function.hrtime.php) Without hrtime precision it might make sense to combine more solutions too.

    bug 
    opened by peteraba 7
  • Update default path to localhost_router.php

    Update default path to localhost_router.php

    I just installed the skeleton, but was receiving this error:

    /project$ php apex app:runlocally
    Running at http://localhost:80
    [Fri Dec 22 11:05:39 2017] PHP Warning:  Unknown: failed to open stream: No such file or directory in Unknown on line 0
    [Fri Dec 22 11:05:39 2017] PHP Fatal error:  Unknown: Failed opening required '/project/public/localhost_router.php' (include_path='.:/usr/share/php') in Unknown on line 0
    

    This patch I am submitting fixed the issue for me.

    bug 
    opened by adamaltman 7
  • ensure ENV_NAME and Environment::name are never out of sync

    ensure ENV_NAME and Environment::name are never out of sync

    The Opulence starter project sets ENV_NAME as an environment variable, and that environment variable is then used to set the Environmnet::name. If the ENV_NAME variable is changed, or the Environment::name member is changed, the two values would no longer have been equal.

    opened by itised 7
  • Suggestion: Add option to clear console cache for apex

    Suggestion: Add option to clear console cache for apex

    One thing I learned is that there's a cache file for console that almost instantly gets cached in tmp/framework/console called cachedBootstrapperRegistry.json and say if you remove a bootstrap class it'll throw a fatal error making apex compeltely unusable because it's looking for a class that doesn't exist anymore.

    My suggestion is to be able to call: php apex --hard-cache-clear which does one thing and that's to clear the cache directly and nothing else that way you won't have to manually do it to get apex working again.

    I'm still learning Opulence, so maybe I'll try creating a PR if I figure it out tonight.

    enhancement 
    opened by exts 6
Releases(6.18.1)
Owner
Max Howell
Max Howell
Easy Swift Futures & Promises.

❗️ Archived now ❗️ Since Apple released Combine framework, I decide to archive this repo. You still can use this repo as an example of Future/Promise

Dmytro Mishchenko 40 Sep 23, 2022
A Swift based Future/Promises Library for IOS and OS X.

FutureKit for Swift A Swift based Future/Promises Library for IOS and OS X. Note - The latest FutureKit is works 3.0 For Swift 2.x compatibility use v

null 759 Dec 2, 2022
Lightweight Promises for Swift & Obj-C

Tomorrowland Tomorrowland is an implementation of Promises for Swift and Objective-C. A Promise is a wrapper around an asynchronous task that provides

Lily Ballard 115 Nov 23, 2022
When is a lightweight implementation of Promises in Swift

Description When is a lightweight implementation of Promises in Swift. It doesn't include any helper functions for iOS and OSX and it's intentional, t

Vadym Markov 259 Dec 29, 2022
RxReduce is a lightweight framework that ease the implementation of a state container pattern in a Reactive Programming compliant way.

About Architecture concerns RxReduce Installation The key principles How to use RxReduce Tools and dependencies Travis CI Frameworks Platform Licence

RxSwift Community 125 Jan 29, 2022
what's the most useless thing you can show on Discord? well, you see,

HealthKitRPC A friend jokingly suggested to have my heart rate visible on Discord. Well... Full of sample code and broken things. Usage Change various

Spotlight 12 Jan 11, 2022
📬 A lightweight implementation of an observable sequence that you can subscribe to.

Features Lightweight Observable is a simple implementation of an observable sequence that you can subscribe to. The framework is designed to be minima

Felix M. 133 Aug 17, 2022
📡 Helping you own NotificationCenter in Swift!

Notificationz ?? Helping you own NotificationCenter Highlights Keep Your Naming Conventions: This library gives you convenient access to NotificationC

Kitz 77 Feb 18, 2022
Pure Declarative Programming in Swift, Among Other Things

Basis The Basis is an exploration of pure declarative programming and reasoning in Swift. It by no means contains idiomatic code, but is instead inten

TypeLift 314 Dec 22, 2022
Gently notifies you about 'important' GitHub notifications

OctoBlast Gently notifies you about important GitHub notifications Setup Personal access token Head to preferences, and pop in your a new GitHub perso

Jason Watson 6 Nov 14, 2022
Write great asynchronous code in Swift using futures and promises

BrightFutures How do you leverage the power of Swift to write great asynchronous code? BrightFutures is our answer. BrightFutures implements proven fu

Thomas Visser 1.9k Dec 20, 2022
Write great asynchronous code in Swift using futures and promises

BrightFutures How do you leverage the power of Swift to write great asynchronous code? BrightFutures is our answer. BrightFutures implements proven fu

Thomas Visser 1.9k Dec 20, 2022
Bookmark important links with categories to read them later on the go!

Kicking Off Hacktoberfest with ACM-VIT! Sticky Links Save link of your favourite websites, articles, videos and pretty much anything! Overview This is

ACM VIT 6 Oct 3, 2022
Allows users to pull in new song releases from their favorite artists and provides users with important metrics like their top tracks, top artists, and recently played tracks, queryable by time range.

Spotify Radar Spotify Radar is an iOS application that allows users to pull in new song releases from their favorite artists and provides users with i

Kevin Li 630 Dec 13, 2022
Link - a macos application for keeping important and complicated urls in one place

Link Description Link is a macos application for keeping important and complicat

Johan Solbakken 2 Jul 21, 2022
Klik - A simple iOS app that helps you with counting things

Klik - A simple iOS app that helps you with counting things

Rostislav Brož 4 Dec 30, 2022
Futures is a cross-platform framework for simplifying asynchronous programming, written in Swift.

Futures Futures is a cross-platform framework for simplifying asynchronous programming, written in Swift. It's lightweight, fast, and easy to understa

David Ask 60 Aug 11, 2022
LibAuthentication will simplify your code when if you want to use FaceID/TouchID in your tweaks.

LibAuthentication will simplify your code when if you want to use FaceID/TouchID in your tweaks.

Maximehip 6 Oct 3, 2022
iOS app to record how much things cost using various data persistence implementations.

how-much iOS app to record how much things cost using various data persistence implementations. The basic data unit is an item, a simple dictionary: {

null 22 Aug 15, 2022
An iOS context menu UI inspired by Things 3.

Contextual menus with delightful animations and styles Total control over menu contents using your own UIViewControllers Tons of feature and interacti

GitHawk 971 Nov 30, 2022