{"action":"created","issue":{"url":"https://api.github.com/repos/strongloop/loopback/issues/418","labels_url":"https://api.github.com/repos/strongloop/loopback/issues/418/labels{/name}","comments_url":"https://api.github.com/repos/strongloop/loopback/issues/418/comments","events_url":"https://api.github.com/repos/strongloop/loopback/issues/418/events","html_url":"https://github.com/strongloop/loopback/issues/418","id":38984704,"number":418,"title":"Support promises","user":{"login":"coodoo","id":325936,"avatar_url":"https://avatars.githubusercontent.com/u/325936?v=3","gravatar_id":"","url":"https://api.github.com/users/coodoo","html_url":"https://github.com/coodoo","followers_url":"https://api.github.com/users/coodoo/followers","following_url":"https://api.github.com/users/coodoo/following{/other_user}","gists_url":"https://api.github.com/users/coodoo/gists{/gist_id}","starred_url":"https://api.github.com/users/coodoo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/coodoo/subscriptions","organizations_url":"https://api.github.com/users/coodoo/orgs","repos_url":"https://api.github.com/users/coodoo/repos","events_url":"https://api.github.com/users/coodoo/events{/privacy}","received_events_url":"https://api.github.com/users/coodoo/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/strongloop/loopback/labels/%23wip","name":"#wip","color":"ededed"},{"url":"https://api.github.com/repos/strongloop/loopback/labels/Beginner%20Friendly","name":"Beginner Friendly","color":"00DD00"},{"url":"https://api.github.com/repos/strongloop/loopback/labels/feature","name":"feature","color":"bfe5bf"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":54,"created_at":"2014-07-29T12:46:05Z","updated_at":"2015-09-02T09:13:34Z","closed_at":null,"body":"LoopBack should provide Promise-enabled API out of the box. The plan is to use the approach outlined in https://github.com/iojs/io.js/pull/173.\r\n\r\n**Tasks**\r\n\r\n - [x] strongloop/strong-remoting#179 support promises in strong-remotin\r\n - [x] strongloop/loopback-datasource-juggler#449 loopback-datasource-juggler - support promises in \"operation hooks\" \r\n - [x]  strongloop/loopback-datasource-juggler#451 and  strongloop/loopback-datasource-juggler#452 loopback-datasource-juggler - convert all DAO & relation methods to dual callback/promise API \r\n - [x] promisify juggler's DataSource methods like `automigrate`, `autoupdate`, `discover*`, etc.\r\n  - https://github.com/strongloop/loopback-datasource-juggler/pull/630\r\n - [ ] convert loopback builtin models to support dual callback/promise API\r\n  - [x] User - https://github.com/strongloop/loopback/pull/1493\r\n  - [x] Application - https://github.com/strongloop/loopback/pull/1533\r\n  - [x] PersistedModel (replication, change tracking) - https://github.com/strongloop/loopback/pull/1536\r\n  - [ ] Change\r\n  - [ ] Checkpoint\r\n  - [ ] Scope\r\n  - [ ] Model.checkAccess()\r\n  - [ ] AccessToken\r\n  - [ ] Role (and role resolvers)\r\n  - [ ] RoleMapping\r\n  - [ ] ACL\r\n - [ ] Promisify `app.listen`\r\n - [ ] Modify connectors and convert all mixin methods to dual callback/promise API\r\n  - [ ] loopback-connector-remote\r\n - (?) Allow middleware handlers to return a promise\r\n - [ ] Update examples and docs\r\n   - [ ] Enhance strong-docs to support `@promise` annotation https://github.com/strongloop-internal/strong-docs/issues/63\r\n   - [ ] Edit API docs / Mark all functions supporting promises with `@promise` attribute #1409 \r\n   - [ ] Wiki docs with basic desc of new promise support (differences, etc) #1575\r\n   - [ ] Add / modify example apps using Promises #1576\r\n  \r\n---\r\n\r\nBelow is the original proposal from @coodoo.\r\n\r\nI've been playing around with bluebird's promisifyAll() for a while, ended up I found it just take a couple of line to wrap the model and make it become async-compatible.\r\n\r\nSee code below:\r\n\r\n```js\r\nvar Promise = require(\"bluebird\");\r\n\r\nmodule.exports = function(ResetKey) {\r\n\r\n// once a model is attached to the data source\r\nResetKey.on('dataSourceAttached', function( obj ){\r\n    \r\n    // wrap the whole model in Promise\r\n   // but we need to avoid 'validate' method \r\n    ResetKey = Promise.promisifyAll( ResetKey, {filter: function(name, func, target){\r\n      return !( name == 'validate');\r\n    }} );\r\n  })\r\n\r\n}\r\n\r\n```\r\n\r\nOnce the model is wrapped, we can use Promise syntax instead of callbacks:\r\n\r\n```js\r\n\r\n// old way - callbacks\r\nuser.save(function(err, result){...})\r\n\r\n// new way - promise\r\nuser.saveAsync()\r\n.then(function(result){...})\r\n.catch(function(err){...})\r\n\r\n```\r\n\r\nAin't that lovely? :)\r\n\r\nOf course it would be even better if all those happened higher up in the chain and become default.\r\n\r\nThought?"},"comment":{"url":"https://api.github.com/repos/strongloop/loopback/issues/comments/136989288","html_url":"https://github.com/strongloop/loopback/issues/418#issuecomment-136989288","issue_url":"https://api.github.com/repos/strongloop/loopback/issues/418","id":136989288,"user":{"login":"alFReD-NSH","id":822510,"avatar_url":"https://avatars.githubusercontent.com/u/822510?v=3","gravatar_id":"","url":"https://api.github.com/users/alFReD-NSH","html_url":"https://github.com/alFReD-NSH","followers_url":"https://api.github.com/users/alFReD-NSH/followers","following_url":"https://api.github.com/users/alFReD-NSH/following{/other_user}","gists_url":"https://api.github.com/users/alFReD-NSH/gists{/gist_id}","starred_url":"https://api.github.com/users/alFReD-NSH/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/alFReD-NSH/subscriptions","organizations_url":"https://api.github.com/users/alFReD-NSH/orgs","repos_url":"https://api.github.com/users/alFReD-NSH/repos","events_url":"https://api.github.com/users/alFReD-NSH/events{/privacy}","received_events_url":"https://api.github.com/users/alFReD-NSH/received_events","type":"User","site_admin":false},"created_at":"2015-09-02T09:13:34Z","updated_at":"2015-09-02T09:13:34Z","body":"There's no mention of email connector or email model here. Don't forget about this one please."}}