{"action":"created","issue":{"url":"https://api.github.com/repos/salesforce/nimbus/issues/116","repository_url":"https://api.github.com/repos/salesforce/nimbus","labels_url":"https://api.github.com/repos/salesforce/nimbus/issues/116/labels{/name}","comments_url":"https://api.github.com/repos/salesforce/nimbus/issues/116/comments","events_url":"https://api.github.com/repos/salesforce/nimbus/issues/116/events","html_url":"https://github.com/salesforce/nimbus/issues/116","id":549216016,"node_id":"MDU6SXNzdWU1NDkyMTYwMTY=","number":116,"title":"[RFC] Supporting reject state for promise created with trailing closure","user":{"login":"sfdctaka","id":42476999,"node_id":"MDQ6VXNlcjQyNDc2OTk5","avatar_url":"https://avatars0.githubusercontent.com/u/42476999?v=4","gravatar_id":"","url":"https://api.github.com/users/sfdctaka","html_url":"https://github.com/sfdctaka","followers_url":"https://api.github.com/users/sfdctaka/followers","following_url":"https://api.github.com/users/sfdctaka/following{/other_user}","gists_url":"https://api.github.com/users/sfdctaka/gists{/gist_id}","starred_url":"https://api.github.com/users/sfdctaka/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sfdctaka/subscriptions","organizations_url":"https://api.github.com/users/sfdctaka/orgs","repos_url":"https://api.github.com/users/sfdctaka/repos","events_url":"https://api.github.com/users/sfdctaka/events{/privacy}","received_events_url":"https://api.github.com/users/sfdctaka/received_events","type":"User","site_admin":false},"labels":[{"id":1186953190,"node_id":"MDU6TGFiZWwxMTg2OTUzMTkw","url":"https://api.github.com/repos/salesforce/nimbus/labels/Type:%20Discussion%20(RFC)","name":"Type: Discussion (RFC)","color":"065f96","default":false,"description":"Request for Comment - Useful to open before major/breaking/non-chore changes"}],"state":"open","locked":false,"assignee":{"login":"threeve","id":3158,"node_id":"MDQ6VXNlcjMxNTg=","avatar_url":"https://avatars0.githubusercontent.com/u/3158?v=4","gravatar_id":"","url":"https://api.github.com/users/threeve","html_url":"https://github.com/threeve","followers_url":"https://api.github.com/users/threeve/followers","following_url":"https://api.github.com/users/threeve/following{/other_user}","gists_url":"https://api.github.com/users/threeve/gists{/gist_id}","starred_url":"https://api.github.com/users/threeve/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/threeve/subscriptions","organizations_url":"https://api.github.com/users/threeve/orgs","repos_url":"https://api.github.com/users/threeve/repos","events_url":"https://api.github.com/users/threeve/events{/privacy}","received_events_url":"https://api.github.com/users/threeve/received_events","type":"User","site_admin":false},"assignees":[{"login":"threeve","id":3158,"node_id":"MDQ6VXNlcjMxNTg=","avatar_url":"https://avatars0.githubusercontent.com/u/3158?v=4","gravatar_id":"","url":"https://api.github.com/users/threeve","html_url":"https://github.com/threeve","followers_url":"https://api.github.com/users/threeve/followers","following_url":"https://api.github.com/users/threeve/following{/other_user}","gists_url":"https://api.github.com/users/threeve/gists{/gist_id}","starred_url":"https://api.github.com/users/threeve/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/threeve/subscriptions","organizations_url":"https://api.github.com/users/threeve/orgs","repos_url":"https://api.github.com/users/threeve/repos","events_url":"https://api.github.com/users/threeve/events{/privacy}","received_events_url":"https://api.github.com/users/threeve/received_events","type":"User","site_admin":false},{"login":"paultiarks","id":331388,"node_id":"MDQ6VXNlcjMzMTM4OA==","avatar_url":"https://avatars2.githubusercontent.com/u/331388?v=4","gravatar_id":"","url":"https://api.github.com/users/paultiarks","html_url":"https://github.com/paultiarks","followers_url":"https://api.github.com/users/paultiarks/followers","following_url":"https://api.github.com/users/paultiarks/following{/other_user}","gists_url":"https://api.github.com/users/paultiarks/gists{/gist_id}","starred_url":"https://api.github.com/users/paultiarks/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/paultiarks/subscriptions","organizations_url":"https://api.github.com/users/paultiarks/orgs","repos_url":"https://api.github.com/users/paultiarks/repos","events_url":"https://api.github.com/users/paultiarks/events{/privacy}","received_events_url":"https://api.github.com/users/paultiarks/received_events","type":"User","site_admin":false},{"login":"jamie-houston","id":30670552,"node_id":"MDQ6VXNlcjMwNjcwNTUy","avatar_url":"https://avatars2.githubusercontent.com/u/30670552?v=4","gravatar_id":"","url":"https://api.github.com/users/jamie-houston","html_url":"https://github.com/jamie-houston","followers_url":"https://api.github.com/users/jamie-houston/followers","following_url":"https://api.github.com/users/jamie-houston/following{/other_user}","gists_url":"https://api.github.com/users/jamie-houston/gists{/gist_id}","starred_url":"https://api.github.com/users/jamie-houston/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jamie-houston/subscriptions","organizations_url":"https://api.github.com/users/jamie-houston/orgs","repos_url":"https://api.github.com/users/jamie-houston/repos","events_url":"https://api.github.com/users/jamie-houston/events{/privacy}","received_events_url":"https://api.github.com/users/jamie-houston/received_events","type":"User","site_admin":false}],"milestone":null,"comments":1,"created_at":"2020-01-13T22:21:10Z","updated_at":"2020-01-14T22:12:59Z","closed_at":null,"author_association":"CONTRIBUTOR","body":"Nimbus currently has a way to turn a native method into Javascript method that returns a promise.  For example let's say that we have a method `foo` in iOS:\r\n```\r\nfunc foo(@escaping callback: (success: String)->Void) {...}\r\n```\r\nand a counterpart in Android:\r\n```\r\nfunc foo(callback: (success: String)->Unit) {...}\r\n```\r\nFor these two methods to be converted into a method that returns a promise in Javascript we need to bind `foo`, for iOS, and indicate that the closure that was passed as a parameter is for promise:\r\n```\r\nconnection.bind(foo, as: \"foo\", trailingClosure: .promise)\r\n```\r\nAnd for Android we need to annotate `foo` with:\r\n```\r\n@ExtensionMethod(trailingClosure = TrailingClosure.PROMISE)\r\nfunc foo(callback:(success:String)-> Unit) {...}\r\n```\r\nIn Javascript the above would translate into code like this:\r\n```\r\nconst promise = foo()\r\n```\r\nBut because this promise currently only supports the resolve state but not the reject state it is only then-able:\r\n```\r\n// Doable:\r\nfoo().then((success) -> {console.log(success);})\r\n// Not doable:\r\nfoo().catch((error) -> {console.log(error);})\r\n// Also not doable:\r\nfoo().then((success) -> {console.log(success);}).catch((error) -> {console.log(error);})\r\n```\r\n\r\nThis RFC lists and explores 3 distinct approaches to support reject state in Nimbus.\r\n\r\n**(1) Method that Throws**\r\nIf a method is declared to throw and is designated as a trailing closure,\r\nin iOS:\r\n```\r\nfunc foo(@escaping callback: (success: String) -> ()) throws {...}\r\nconnection.bind(foo, as: \"foo\", trailingClosure: .promise)\r\n```\r\nin Android:\r\n```\r\n@Throws(IOException::class)\r\n@ExtensionMethod(trailingClosure = TrailingClosure.PROMISE)\r\nfun foo(callback: (success: String) -> Unit) {...}\r\n```\r\nthen we can consider that promise for these methods will need to support both resolve and reject. All exceptions will be converted into 'something'(string message??).\r\n\r\nPro: Fairly easy to implement\r\nCon: Exception thrown will lose information when it gets to Javascript as a string message. What type of data should reject state pass back??\r\n\r\n**(2) Closure with Two Arguments**\r\nIf a method is passed a closure with two arguments and this closure is indicated as promise\r\nin iOS:\r\n```\r\nfunc foo(@escaping callback: (success: String?, error: String?) -> ()) {...}\r\nconnection.bind(foo, as: \"foo\", trailingClosure: .promise)\r\n```\r\nin Android:\r\n```\r\n@ExtensionMethod(trailingClosure = TrailingClosure.PROMISE)\r\nfun foo(callback: (success: String?, error: String?) -> ()) {...}\r\n```\r\nthen we can use this same closure to callback for both resolved and rejected states.  The distinction for the two states are made by one of the arguments to the closure being a null but not both.\r\n\r\nPro: Fairly easy to implement\r\nCon: Should the type for error parameter be constrained to specific type???\r\n\r\n**(3) Second Closure As Parameter**\r\nIf a method is passed **two** closures and these closures are marked for the promise's resolve and reject callbacks,\r\nin iOS:\r\n```\r\nfunc foo(@escaping success: (String) -> (), @escaping error: (String) -> ()) {...}\r\nconnection.bind(foo, as: \"foo\", trailingClosure: .promiseResolveAndReject)\r\n```\r\nin Android:\r\n```\r\n@ExtensionMethod(trailingClosure = TrailingClosure.PROMISE_RESOLVE_AND_REJECT)\r\nfun foo(success: (String) -> Unit, error: (String) -> Unit) {...}\r\n```\r\nthen we can use respective closure to notify resolve and reject states.\r\n\r\nPro: Easier to read than the previous 2 approaches.\r\nCon: More code to write than the previous 2 approaches.\r\n\r\n"},"comment":{"url":"https://api.github.com/repos/salesforce/nimbus/issues/comments/574399078","html_url":"https://github.com/salesforce/nimbus/issues/116#issuecomment-574399078","issue_url":"https://api.github.com/repos/salesforce/nimbus/issues/116","id":574399078,"node_id":"MDEyOklzc3VlQ29tbWVudDU3NDM5OTA3OA==","user":{"login":"sfdctaka","id":42476999,"node_id":"MDQ6VXNlcjQyNDc2OTk5","avatar_url":"https://avatars0.githubusercontent.com/u/42476999?v=4","gravatar_id":"","url":"https://api.github.com/users/sfdctaka","html_url":"https://github.com/sfdctaka","followers_url":"https://api.github.com/users/sfdctaka/followers","following_url":"https://api.github.com/users/sfdctaka/following{/other_user}","gists_url":"https://api.github.com/users/sfdctaka/gists{/gist_id}","starred_url":"https://api.github.com/users/sfdctaka/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sfdctaka/subscriptions","organizations_url":"https://api.github.com/users/sfdctaka/orgs","repos_url":"https://api.github.com/users/sfdctaka/repos","events_url":"https://api.github.com/users/sfdctaka/events{/privacy}","received_events_url":"https://api.github.com/users/sfdctaka/received_events","type":"User","site_admin":false},"created_at":"2020-01-14T22:12:59Z","updated_at":"2020-01-14T22:12:59Z","author_association":"CONTRIBUTOR","body":"@threeve Thanks, and will do the markdown!"}}
{"actor":{"display_login":"sfdctaka"}}