{"action":"created","issue":{"url":"https://api.github.com/repos/tomlokhorst/Promissum/issues/2","labels_url":"https://api.github.com/repos/tomlokhorst/Promissum/issues/2/labels{/name}","comments_url":"https://api.github.com/repos/tomlokhorst/Promissum/issues/2/comments","events_url":"https://api.github.com/repos/tomlokhorst/Promissum/issues/2/events","html_url":"https://github.com/tomlokhorst/Promissum/issues/2","id":53721147,"number":2,"title":"Support dispatching on GCD queues","user":{"login":"tomlokhorst","id":75655,"avatar_url":"https://avatars.githubusercontent.com/u/75655?v=3","gravatar_id":"","url":"https://api.github.com/users/tomlokhorst","html_url":"https://github.com/tomlokhorst","followers_url":"https://api.github.com/users/tomlokhorst/followers","following_url":"https://api.github.com/users/tomlokhorst/following{/other_user}","gists_url":"https://api.github.com/users/tomlokhorst/gists{/gist_id}","starred_url":"https://api.github.com/users/tomlokhorst/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tomlokhorst/subscriptions","organizations_url":"https://api.github.com/users/tomlokhorst/orgs","repos_url":"https://api.github.com/users/tomlokhorst/repos","events_url":"https://api.github.com/users/tomlokhorst/events{/privacy}","received_events_url":"https://api.github.com/users/tomlokhorst/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":1,"created_at":"2015-01-08T07:03:31Z","updated_at":"2015-02-28T21:55:57Z","closed_at":null,"body":"Current (2015-01-08) behaviour is that every callback (from `map`, `then` and the like) happen synchronously on the same thread as where `PromiseSource.resolve` is called. Lets call this \"synchronous dispatch\".\r\n\r\nSometimes synchronous dispatch is the correct behaviour, but most of the time it leads to unexpected results.\r\n\r\nProposal: add dispatchOn\r\n------\r\n\r\nAdd support to \"configure\" a promise to run on a provided dispatch queue. For example:\r\n\r\n    let myQueue = dispatch_queue_create(\"com.example.MyQueue\", nil);\r\n\r\n    getSomePromise()\r\n      .dispatchOn(myQueue)\r\n      .map { value in\r\n        // This is called on my queue\r\n        return value\r\n      }\r\n      .then { value in\r\n        // This is also called on my queue\r\n        // That means we can't do UI operations! (not UI thread)\r\n      }\r\n\r\nThe call to `dispatchOn(queue: dispatch_queue_t)` returns a new Promise that is correctly configured (i.e. it doesn't mutate the existing promise). This way we can also \"switch\" queues:\r\n\r\n    getSomePromise()\r\n      .dispatchOn(myQueue)\r\n      .map { value in\r\n        // This is called on my queue\r\n        return value\r\n      }\r\n      .dispatchOn(dispatch_get_main_queue())\r\n      .then { value in\r\n        // This runs on main thread, so we can do UI operations\r\n      }\r\n\r\nWhen nothing is configured, the main queue is chosen as a default (so users can do UI operations):\r\n\r\n    getSomePromise()\r\n      .then { value in\r\n        // Default: run on main thread\r\n      }\r\n\r\nHowever, if for some reason, you want to dispatch synchronously, this can be done using `dispatchSync()`:\r\n\r\n    getSomePromise()\r\n      .dispatchSync()\r\n      .then { value in\r\n        // This now runs on whatever thread `PromiseSource.resolve` was called on.\r\n        // This can be used if the caller of `resolve` expects the side effects from `then` to have happend.\r\n      }\r\n\r\nRunning a \"sub computation\" on a different queue is also possible, using the existing `flatMap`:\r\n\r\n    getSomePromise()\r\n      .dispatchOn(myQueue)\r\n      .flatMap { value in\r\n        return Promise(value: value)\r\n          .dispatchOn(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0))\r\n          .map { val in\r\n            // This runs on a high priority queue\r\n            return val\r\n          }\r\n      }\r\n      .then { value in\r\n        // This is also called on my queue\r\n        // That means we can't do UI operations! (not UI thread)\r\n      }"},"comment":{"url":"https://api.github.com/repos/tomlokhorst/Promissum/issues/comments/76549080","html_url":"https://github.com/tomlokhorst/Promissum/issues/2#issuecomment-76549080","issue_url":"https://api.github.com/repos/tomlokhorst/Promissum/issues/2","id":76549080,"user":{"login":"tomlokhorst","id":75655,"avatar_url":"https://avatars.githubusercontent.com/u/75655?v=3","gravatar_id":"","url":"https://api.github.com/users/tomlokhorst","html_url":"https://github.com/tomlokhorst","followers_url":"https://api.github.com/users/tomlokhorst/followers","following_url":"https://api.github.com/users/tomlokhorst/following{/other_user}","gists_url":"https://api.github.com/users/tomlokhorst/gists{/gist_id}","starred_url":"https://api.github.com/users/tomlokhorst/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tomlokhorst/subscriptions","organizations_url":"https://api.github.com/users/tomlokhorst/orgs","repos_url":"https://api.github.com/users/tomlokhorst/repos","events_url":"https://api.github.com/users/tomlokhorst/events{/privacy}","received_events_url":"https://api.github.com/users/tomlokhorst/received_events","type":"User","site_admin":false},"created_at":"2015-02-28T21:55:57Z","updated_at":"2015-02-28T21:55:57Z","body":"For reference, this is being worked on in this branch: https://github.com/tomlokhorst/Promissum/tree/feature/dispatch-method"}}