yannickl / awaitkit Goto Github PK
View Code? Open in Web Editor NEWThe ES8 Async/Await control flow for Swift
License: MIT License
The ES8 Async/Await control flow for Swift
License: MIT License
Currently AwaitKit points fuzzily at 4.x, but 4.5.1 raises it's deployment target version to 10.11.
If there's no appetite to increment the deployment target to 10.11, the alternative is to pin the PromiseKit version in the podspec
Happy to PR this if needed.
It just crashes with a SIGABRT everytime await is used.
Does not happen with Promise Kit 6.2.9
Is there any chance that you add support for Guarantees?
Hi,
How could I pass an instruction which uses Elvis Operator? Example:
try await(myObject?.myPromiseMethod())
Thanks.
As the title suggests, though AwaitKit is still supporting iOS 8. PromiseKit requires that the SDK must be later than iOS 12. And Xcode will show an error when building with AwaitKit.
Proof of concept with using AwaitKit, I'm using URLSession.dataTask
to perform a request and get a response, asynchronously and non-blocking (so, by using async { }
in a background thread).
This code is the first code in viewDidLoad
in the default ViewController
in a new project.
func doRequest() -> Promise<URLResponse?> {
return Promise { resolve, reject in
URLSession.shared.dataTask(with: URL(string: "https://httpstat.us/200?sleep=1000")!) { (data, response, error) in
if (error != nil) {
return reject(error!)
}
return resolve(response)
}
}
}
async {
let response = try await(doRequest())
print(response)
}
However, we never get to print(response)
, no errors are thrown, nothing happens. Am I using this library correctly?
EDIT: Figured out this was the same problem as in a previous issue.
Hello,
I have the following code:
do {
try await(LoginProvider.FIRLogin(with: email, password: password))
print("ended")
} catch {
handleErrors()
}
...
static func FIRLogin(with email: String, password: String) -> Promise<Firebase.User> {
return Promise { Auth.auth().signIn(withEmail: email, password: password, completion: $0.resolve) }
}
Why does the print never appear?
The DispatchQueue extension in this library which adds the .async method conflicts with the one provided by swift 3.0 (dispatch_async was replaced with DispatchQueue.async). Explicitly specifying the parameter name (execute:) works around the issue but I think this extension method needs to be renamed so that it does not conflict with iOS standard libs.
I'm trying to use this library along with PromiseKit. I'm using their URLSession extensions to get a very nice looking asynchronous HTTP request:
let res = try! await(URLSession.shared.dataTask(.promise, with: url).validate())
However, my program is freezing here and never returning from the await. Am I doing something stupid?
The introduction of async/await in Swift 5.5 (https://github.com/apple/swift-evolution/blob/main/proposals/0296-async-await.md) promoted the "await" word to keyword. Therefore to use it in the context of function call, it must be wrapped in backticks, just as for the methods called with other language keywords.
I've made a PR that adds the backticks in the right place: #57
Change is compatible with previous Swift versions.
Hi! This library looks really great and I'm considering to include it into a new project. However I have a theory question I'd like to get an answer to before doing that. I was wondering if the following scenario was possible:
async
something, which gets executed in the "async" concurrent queue, which runs in thread A.await
for something, which locks thread A, and that something runs on thread B.async
block), but thread A is also awaiting for thread B to resolve its promise. Then there's a deadlock and there's no way of getting out of it.Thank you in advance, and as I'm sure something like StackOverflow would be better to ask this kind of questions, I also know there's no better person to answer it than the creator of the framework himself.
Hi! I am trying to install via spm:
.package(url: "https://github.com/yannickl/AwaitKit.git", from: "5.1.0")
I get:
https://github.com/yannickl/AwaitKit.git @ 5.1.0: error: manifest parse error(s):
Invalid version string: 6.7
Xcode: 10.2.1
macOS Mojave 10.14.5
Any ideas? Thank You.
Hello,
do you think you can update podspec file to require only PromiseKit/CorePromise as it is enough for AwaitKit to work (I believe). I am using just CorePromise in my projects and it then fights with AwaitKits requirements :(
is there a way to mix an async {} block of code with UI actions that has promises? something like PMKAlertController.
I have also developed other ViewControllers that waits for an user action and when said VC is dismissed it fulfill/reject a promise. Can AwaitKit wait for that promise to fulfill, but don't block the main UI, nor glitch the drawing of the UI when is getting presented because is in a background thread?
Hello!
Maybe this is a stupid question but I haven't been able to solve it as of yet.
I have something like
async {
let report = try await(self.reportStore.getReport())
//update UI
}
As I am inside the async I am not in the main thread and get whacky behaviour on the UI. But if I call the await in the main thread I get a deadlock on the semaphore wait. what should I do if I want to get back to the main thread with my result?
Thanks
Create a new swift3
branch and update the APIs to be conform to the Swift API Guideline.
I've have installed AwaitKit in a project, however have not started to implement it. The addition of it however has now started my Unit Test's to fail with -
Main Thread Checker: UI API called on a background thread: -[UIViewController init]
PID: 10379, TID: 237476, Thread name: (none), Queue name: com.yannickloriot.asyncqueue, QoS: 0
Backtrace:
4 OAuthKit 0x000000010a61fc33 $sSo16UIViewControllerCABycfcTO + 19
5 OAuthKit 0x000000010a61c57f $sSo16UIViewControllerCABycfC + 31
6 OAuthKit 0x000000010a61c2be $s8OAuthKit0A8ProviderC06createA7Manager33_430562AB130E806488074CBA323B7784LL0A5Swift06OAuth2J0CyF + 1470
7 OAuthKit 0x000000010a618657 $s8OAuthKit0A8ProviderCACycfc + 775
8 OAuthKit 0x000000010a6182ec $s8OAuthKit0A8ProviderCACycfC + 60
9 SomeAppName 0x000000010a2018fb $s10SomeAppName16CoreDependenciesC13oauthProvider33_68CD4A43F5E2D568288F593D3DE6E3FCLL8OAuthKit0rG4Type_pvg + 539
10 SomeAppName 0x000000010a201c53 $s10SomeAppName16CoreDependenciesC7authSvcAA15AuthServiceType_pvg + 547
11 SomeAppName 0x000000010a202230 $s10SomeAppName16CoreDependenciesCAA10DependencyA2aDP7authSvcAA15AuthServiceType_pvgTW + 16
12 SomeAppName 0x000000010a1f6b2e $s10SomeAppName15StartInteractorC14checkAuthState10PromiseKit0I0CyytGyF + 238
13 SomeAppName 0x000000010a1f6cf9 $s10SomeAppName15StartInteractorCAA0D7UseCaseA2aDP14checkAuthState10PromiseKit0K0CyytGyFTW + 9
14 SomeAppName 0x000000010a1f7517 $s10SomeAppName14StartPresenterC14checkAuthState33_A43D4EBCFE4D52FAD1D88C1B3EB067FBLLyyFyyKcfU_ + 87
15 SomeAppName 0x000000010a1f7674 $s10SomeAppName14StartPresenterC14checkAuthState33_A43D4EBCFE4D52FAD1D88C1B3EB067FBLLyyFyyKcfU_TA + 20
16 AwaitKit 0x000000010a5b53ef $ss5Error_pIegzo_ytsAA_pIegrzo_TR + 15
17 AwaitKit 0x000000010a5b5484 $ss5Error_pIegzo_ytsAA_pIegrzo_TRTA + 20
18 PromiseKit 0x000000010a881943 $sSo17OS_dispatch_queueC10PromiseKitE5async_5group3qos5flags7executeAC0D0CyxGAC13PMKNamespacerO_So0a1_b1_G0CSg8Dispatch0L3QoSVAQ0L13WorkItemFlagsVxyKctlFyycfU_ + 275
19 PromiseKit 0x000000010a856bcd $sIeg_IeyB_TR + 45
20 libdispatch.dylib 0x00007fff516ba274 _dispatch_block_async_invoke2 + 83
21 libdispatch.dylib 0x00007fff516ad781 _dispatch_client_callout + 8
22 libdispatch.dylib 0x00007fff516afb3d _dispatch_continuation_pop + 440
23 libdispatch.dylib 0x00007fff516af209 _dispatch_async_redirect_invoke + 817
24 libdispatch.dylib 0x00007fff516bcbfc _dispatch_root_queue_drain + 350
25 libdispatch.dylib 0x00007fff516bd39e _dispatch_worker_thread2 + 99
26 libsystem_pthread.dylib 0x00007fff518d16d5 _pthread_wqthread + 220
27 libsystem_pthread.dylib 0x00007fff518d157b start_wqthread + 15
2019-11-22 05:23:06.834770+0000 SomeAppName[10379:237476] [reports] Main Thread Checker: UI API called on a background thread: -[UIViewController init]
PID: 10379, TID: 237476, Thread name: (none), Queue name: com.yannickloriot.asyncqueue, QoS: 0
Backtrace:
4 OAuthKit 0x000000010a61fc33 $sSo16UIViewControllerCABycfcTO + 19
5 OAuthKit 0x000000010a61c57f $sSo16UIViewControllerCABycfC + 31
6 OAuthKit 0x000000010a61c2be $s8OAuthKit0A8ProviderC06createA7Manager33_430562AB130E806488074CBA323B7784LL0A5Swift06OAuth2J0CyF + 1470
7 OAuthKit 0x000000010a618657 $s8OAuthKit0A8ProviderCACycfc + 775
8 OAuthKit 0x000000010a6182ec $s8OAuthKit0A8ProviderCACycfC + 60
9 SomeAppName 0x000000010a2018fb $s10SomeAppName16CoreDependenciesC13oauthProvider33_68CD4A43F5E2D568288F593D3DE6E3FCLL8OAuthKit0rG4Type_pvg + 539
10 SomeAppName 0x000000010a201c53 $s10SomeAppName16CoreDependenciesC7authSvcAA15AuthServiceType_pvg + 547
11 SomeAppName 0x000000010a202230 $s10SomeAppName16CoreDependenciesCAA10DependencyA2aDP7authSvcAA15AuthServiceType_pvgTW + 16
12 SomeAppName 0x000000010a1f6b2e $s10SomeAppName15StartInteractorC14checkAuthState10PromiseKit0I0CyytGyF + 238
13 SomeAppName 0x000000010a1f6cf9 $s10SomeAppName15StartInteractorCAA0D7UseCaseA2aDP14checkAuthState10PromiseKit0K0CyytGyFTW + 9
14 SomeAppName 0x000000010a1f7517 $s10SomeAppName14StartPresenterC14checkAuthState33_A43D4EBCFE4D52FAD1D88C1B3EB067FBLLyyFyyKcfU_ + 87
15 SomeAppName 0x000000010a1f7674 $s10SomeAppName14StartPresenterC14checkAuthState33_A43D4EBCFE4D52FAD1D88C1B3EB067FBLLyyFyyKcfU_TA + 20
16 AwaitKit 0x000000010a5b53ef $ss5Error_pIegzo_ytsAA_pIegrzo_TR + 15
17 AwaitKit 0x000000010a5b5484 $ss5Error_pIegzo_ytsAA_pIegrzo_TRTA + 20
18 PromiseKit 0x000000010a881943 $sSo17OS_dispatch_queueC10PromiseKitE5async_5group3qos5flags7executeAC0D0CyxGAC13PMKNamespacerO_So0a1_b1_G0CSg8Dispatch0L3QoSVAQ0L13WorkItemFlagsVxyKctlFyycfU_ + 275
19 PromiseKit 0x000000010a856bcd $sIeg_IeyB_TR + 45
20 libdispatch.dylib 0x00007fff516ba274 _dispatch_block_async_invoke2 + 83
21 libdispatch.dylib 0x00007fff516ad781 _dispatch_client_callout + 8
22 libdispatch.dylib 0x00007fff516afb3d _dispatch_continuation_pop + 440
23 libdispatch.dylib 0x00007fff516af209 _dispatch_async_redirect_invoke + 817
24 libdispatch.dylib 0x00007fff516bcbfc _dispatch_root_queue_drain + 350
25 libdispatch.dylib 0x00007fff516bd39e _dispatch_worker_thread2 + 99
26 libsystem_pthread.dylib 0x00007fff518d16d5 _pthread_wqthread + 220
27 libsystem_pthread.dylib 0x00007fff518d157b start_wqthread + 15
(lldb)
The only way around this for now is to disable the main thread checker
in my test scheme, which I'd rather not do. I'm a little confused as to why this is happening and how to fix it.
Hey! Friendly neighborhood JavaScript developer here :) I'm writing some Swift and someone pointed me to this library (it looks amazing!) but I noticed a slight error in the repo description — async/await
are part of the ES2017 / "ES7" specification, not the ES8 specification (https://tc39.github.io/ecma262/2017/#sec-async-function-definitions).
Don't mean to be /that/ pedantic guy, just figured it'd be a quick fix 😅
Hi, I'm using AwaitKit in my new Swift project.
How can I return nil through resolve method,
private func requestHandshake() -> Promise<HandshakeModel> {
return Promise { resolve, reject in
RequestRPModel<ResponseVOModel<HandshakeModel>>().configure {
$0.APIPath = API.Common.handshake
$0.completion = { (response) in
if let result = response as? ResponseVOModel<HandshakeModel> {
//for Succeed
if let handshake = result.data {//check handshake data
//show notice
if let notice = handshake.notice {
JDFacade.ux.alert(notice.contents!, completion: {
if notice.action == 1 {//exit
assert(false)
}
})
}
resolve(handshake)
return
}
}
resolve(nil)
}
}.request()
}
I have an await operation, a URLSessionDataTask. And a UIView animation as progress bar. However, the animation won't start until the await operation finishes. That is not what I expects, I want it to animate along the await operation.
The animation is UIView.animate(withDuration:delay:options:animations:completion:).
Is this possible?
Steps:
Any chance of a patch release with the package.swift update? It's not possible to add this as a dependency currently without it. Commit hash is ad8e892.
Hello @yannickl,
Love the framework, great work!
Maybe it is connected to #16, building the app with the iOS11 SDK, it crashes on the device (not on simulator, though).
The exception brake point stops at DispatchQueue+AwaitKit,swift line 79.
My app has been running on simulator perfectly fine. I tried to load it on my device (iPhone XS, iOS 12.1.2), and a window popped up in Xcode saying Could not launch "MyApp", internal error
.
I looked at the device logs from Window > Devices and Simulators and I see a crash log from my app. In the logs, I see a message:
Exception Type: EXC_CRASH (SIGABRT)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Exception Note: EXC_CORPSE_NOTIFY
Termination Description: DYLD, Library not loaded: @rpath/libswiftCore.dylib | Referenced from: /private/var/containers/Bundle/Application/FFBD3A48-511D-48E6-A14B-C8207A7F2DCA/HackerNews.app/Frameworks/AwaitKit.framework/AwaitKit | Reason: Incompatible library version: AwaitKit requires version 1.0.0 or later, but libswiftCore.dylib provides version 0.0.0
Triggered by Thread: 0
I am using the latest version of AwaitKit and PromiseKit.
My app have a dispatchQ
(DispatchQueue) for network requests and most other operations, and some other queues for heavy computing. I use PromiseKit like this,
fetchData().then { objects in
let tasks = objects.map { calculate($0 }
return when(fulfilled: tasks)
}.done {
}.catch { error in
}
PromiseKit is simple, I just use promise to replace those callbacks. Now I try to use AwaitKit, but soon I find out that await
blocks current queue. dispatchQ
can never be blocked because while waiting for network responses, the app might doing other small tasks in dispatchQ
. I try to create awaitQ
for waiting tasks like this,
let awaitQ = DispatchQueue(label: "await")
awaitQ.ak.async {
let objects = try await(fetchData())
let tasks = let tasks = objects.map { calculate($0 }
try await(when(fulfilled: tasks))
}
However, because dispatchQ
have other tasks, awaitQ
will still be blocked while waiting for one task. I will try to use DispatchQueue.global(qos: .userInitiated)
to start more threads for waiting.
So, what is the best practice for app like this? Is it OK to start lots of threads for await
?
I've been trying to build this library, using Carthage, but it's failed with error:
error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.
Is something can be done about it?
The code is like this
import UIKit
import PromiseKit
import AwaitKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let urlRequest = URLRequest(url: URL(string: "https://zhaoxin.pro")!)
if let (data, response) = try? await(URLSession.shared.dataTask(.promise, with: urlRequest)) {
let httpURLResponse = response as! HTTPURLResponse
}
}
}
on the
if
line, ".../ViewController.swift:19:40: Type of expression is ambiguous without more context" with Carthage build with xcframework.
With CocoaPods, everything is fine.
for PromiseKit usage:
when(xxx, xxx).then { r1, r2 in
....
}
adding for AwaitKit? just like:
let (r1, r2) = try await(xxx, xxx)
i'm run in Simulator it's work fine.
but i'm run Arachive, there some errors that:
Error : Command failed due to signal : Segmentation fault: 11
0 swift 0x0000000109f7366b llvm::sys::PrintStackTrace(llvm::raw_ostream&) + 43
1 swift 0x0000000109f72956 llvm::sys::RunSignalHandlers() + 70
2 swift 0x0000000109f73ccf SignalHandler(int) + 287
3 libsystem_platform.dylib 0x00007fff9865f52a _sigtramp + 26
4 libsystem_platform.dylib 0x00000000000003b4 _sigtramp + 1738149540
5 swift 0x0000000107e0f16d emitApplyArgument((anonymous namespace)::IRGenSILFunction&, swift::SILValue, swift::SILParameterInfo, swift::irgen::Explosion&) + 365
6 swift 0x0000000107e0e971 (anonymous namespace)::IRGenSILFunction::visitFullApplySite(swift::FullApplySite) + 2497
7 swift 0x0000000107dfc23b swift::irgen::IRGenModule::emitSILFunction(swift::SILFunction) + 9787
8 swift 0x0000000107d575c8 swift::irgen::IRGenModuleDispatcher::emitGlobalTopLevel() + 600
9 swift 0x0000000107de304e performIRGeneration(swift::IRGenOptions&, swift::ModuleDecl, swift::SILModule, llvm::StringRef, llvm::LLVMContext&, swift::SourceFile, unsigned int) + 1278
10 swift 0x0000000107de34f6 swift::performIRGeneration(swift::IRGenOptions&, swift::SourceFile&, swift::SILModule, llvm::StringRef, llvm::LLVMContext&, unsigned int) + 70
11 swift 0x0000000107cc6c8c performCompile(swift::CompilerInstance&, swift::CompilerInvocation&, llvm::ArrayRef, int&) + 15004
12 swift 0x0000000107cc268d frontend_main(llvm::ArrayRef, char const, void) + 2781
13 swift 0x0000000107cbe0ac main + 1932
14 libdyld.dylib 0x00007fff8dbee5ad start + 1
15 libdyld.dylib 0x000000000000006a start + 1916869310
Stack dump:
Impossible to install PromiseKit 6.0 because awaitkit depend to PK4.0. Please update as fast as you can !
i'm use cocoaspod 0.39, when i'm run pod update, there some errors below:
[!] Unable to find a specification for AwaitKit (~> 1.0.0)
the awaitkit must to use cocoapod 1.0.0?
Do we need the reject callback inside a promise?
The below code seems to be working out for me, it catches any error and instead of rejecting it returns null in the resolve function.
Is this bad code, if so why?
function fecthDB() {
return new Promise((resolve, reject) => {
try {
db.query('SELECT * FROM users' (err, result) => {
if (err || !results) {
return resolve(null)
}
resolve(result)
})
} catch (e) {
resolve(null)
}
})
}
function async getUsers() {
var users = await fecthDB()
if (!users) { // error handling
return console.log('error')
}
console.log(users) // got users
}
I got a class which has a method encapsulating KingfisherManager.shared.retrieveImage. This method returns a Promise. It always worked well. However, after I have started to use AwaitKit KingfisherManager.shared.retrieveImage it stucks, not trigering callback.
Works on simulator but not on real device.
Thanks for the help in advance.
My app was crashing and I'm pretty sure it was because Carthage was pulling in AwaitKit 6.8.3.
dyld: lazy symbol binding failed: Symbol not found: _$S10PromiseKit8ThenablePAAE4then2on5flags_AA0A0Cy1TQyd__GSo17OS_dispatch_queueCSg_8Dispatch0J13WorkItemFlagsVSgqd__AIQzKctAaBRd__lFfA0_
Referenced from: Frameworks/AwaitKit.framework/AwaitKit
Expected in: Frameworks/PromiseKit.framework/PromiseKit
dyld: Symbol not found: _$S10PromiseKit8ThenablePAAE4then2on5flags_AA0A0Cy1TQyd__GSo17OS_dispatch_queueCSg_8Dispatch0J13WorkItemFlagsVSgqd__AIQzKctAaBRd__lFfA0_
Referenced from: Frameworks/AwaitKit.framework/AwaitKit
Expected in: Frameworks/PromiseKit.framework/PromiseKit
I added the following to my Cartfile and the issue was resolved.
github "mxcl/PromiseKit" == 6.7.1
Thought you might like to know, Thanks, cool library. :)
It would be great to get a tagged version with Swift 5 support.
I have a function:
func find(name: String, complete: (([Result])->Void))
I want to convert to a function something like this:
func find(name: String) -> Promise<Element?> {
find(name: name) {
(result) in
switch result {
case .success(let elements):
if let element = elements {
// ??? How to return the element
}
case .failure(let error):
print(error)
// ??? How to return nil
}
}
}
The example is really simple one. Can AwaitKit
used for the case like my example?
Hi,
new xCode 14 warning:
Thread running at QOS_CLASS_USER_INITIATED waiting on a lower QoS thread running at QOS_CLASS_DEFAULT. Investigate ways to avoid priority inversions
It's not possible to build the project with XCode 10.2:
The target “PromiseKit” contains source code developed with Swift 3.x.
This version of Xcode does not support building or migrating Swift 3.x targets.
I recently updated the dependencies on my project and migrated to XCode 10 (Swift 4.2), and am now getting the following error when attempting to run an async {}
call:
dyld: Symbol not found: _$S10PromiseKit10CatchMixinPAAE5catch2on6policy_AA12PMKFinalizerCSo17OS_dispatch_queueCSg_AA0C6PolicyOys5Error_pctFfA_
Referenced from: /Users/timfall/Library/Developer/CoreSimulator/Devices/AC33C793-B0CF-4734-8B02-21547E653088/data/Containers/Bundle/Application/A6ECAD16-8B83-4D4B-9D31-EB4E0E9A085C/WikiMessage.app/PlugIns/WikiMessage MessagesExtension.appex/../../Frameworks/AwaitKit.framework/AwaitKit
Expected in: /Users/timfall/Library/Developer/CoreSimulator/Devices/AC33C793-B0CF-4734-8B02-21547E653088/data/Containers/Bundle/Application/A6ECAD16-8B83-4D4B-9D31-EB4E0E9A085C/WikiMessage.app/PlugIns/WikiMessage MessagesExtension.appex/../../Frameworks/PromiseKit.framework/PromiseKit
The line in reference is the following function:
func getSearchResults(searchText: String) -> [Wikipedia] {
async {
searchResults = try! await(networkFunctions.searchForArticle(searchText: searchText))
}
return searchResults
}
I'm guessing it's a breaking change with the PromiseKit
version required for XCode 10?
Here's my Cartfile.resolved
:
github "SwiftyJSON/SwiftyJSON" "4.1.0"
github "hyperoslo/Whisper" "6.0.2"
github "mxcl/PromiseKit" "6.4.0"
github "onevcat/Kingfisher" "4.9.0"
github "yannickl/AwaitKit" "5.0.0"
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.