{"action":"created","issue":{"url":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/issues/551","labels_url":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/issues/551/labels{/name}","comments_url":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/issues/551/comments","events_url":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/issues/551/events","html_url":"https://github.com/GoogleCloudPlatform/gcloud-node/issues/551","id":74408061,"number":551,"title":"Why don't we use promises in our API?","user":{"login":"jgeewax","id":112928,"avatar_url":"https://avatars.githubusercontent.com/u/112928?v=3","gravatar_id":"","url":"https://api.github.com/users/jgeewax","html_url":"https://github.com/jgeewax","followers_url":"https://api.github.com/users/jgeewax/followers","following_url":"https://api.github.com/users/jgeewax/following{/other_user}","gists_url":"https://api.github.com/users/jgeewax/gists{/gist_id}","starred_url":"https://api.github.com/users/jgeewax/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jgeewax/subscriptions","organizations_url":"https://api.github.com/users/jgeewax/orgs","repos_url":"https://api.github.com/users/jgeewax/repos","events_url":"https://api.github.com/users/jgeewax/events{/privacy}","received_events_url":"https://api.github.com/users/jgeewax/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/labels/question","name":"question","color":"cc317c"},{"url":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/labels/wontfix","name":"wontfix","color":"ffffff"}],"state":"closed","locked":false,"assignee":null,"milestone":{"url":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/milestones/12","html_url":"https://github.com/GoogleCloudPlatform/gcloud-node/milestones/Core%20Future","labels_url":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/milestones/12/labels","id":964238,"number":12,"title":"Core Future","description":"","creator":{"login":"jgeewax","id":112928,"avatar_url":"https://avatars.githubusercontent.com/u/112928?v=3","gravatar_id":"","url":"https://api.github.com/users/jgeewax","html_url":"https://github.com/jgeewax","followers_url":"https://api.github.com/users/jgeewax/followers","following_url":"https://api.github.com/users/jgeewax/following{/other_user}","gists_url":"https://api.github.com/users/jgeewax/gists{/gist_id}","starred_url":"https://api.github.com/users/jgeewax/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jgeewax/subscriptions","organizations_url":"https://api.github.com/users/jgeewax/orgs","repos_url":"https://api.github.com/users/jgeewax/repos","events_url":"https://api.github.com/users/jgeewax/events{/privacy}","received_events_url":"https://api.github.com/users/jgeewax/received_events","type":"User","site_admin":false},"open_issues":14,"closed_issues":15,"state":"open","created_at":"2015-02-03T19:55:27Z","updated_at":"2015-05-09T17:58:06Z","due_on":null,"closed_at":null},"comments":6,"created_at":"2015-05-08T15:51:35Z","updated_at":"2015-05-10T02:32:07Z","closed_at":"2015-05-08T16:59:45Z","body":"Seems like we're passing callbacks in rather than getting promises back -- was this an explicit choice?\r\n\r\n/cc @idosela"},"comment":{"url":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/issues/comments/100574160","html_url":"https://github.com/GoogleCloudPlatform/gcloud-node/issues/551#issuecomment-100574160","issue_url":"https://api.github.com/repos/GoogleCloudPlatform/gcloud-node/issues/551","id":100574160,"user":{"login":"idosela","id":174246,"avatar_url":"https://avatars.githubusercontent.com/u/174246?v=3","gravatar_id":"","url":"https://api.github.com/users/idosela","html_url":"https://github.com/idosela","followers_url":"https://api.github.com/users/idosela/followers","following_url":"https://api.github.com/users/idosela/following{/other_user}","gists_url":"https://api.github.com/users/idosela/gists{/gist_id}","starred_url":"https://api.github.com/users/idosela/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/idosela/subscriptions","organizations_url":"https://api.github.com/users/idosela/orgs","repos_url":"https://api.github.com/users/idosela/repos","events_url":"https://api.github.com/users/idosela/events{/privacy}","received_events_url":"https://api.github.com/users/idosela/received_events","type":"User","site_admin":false},"created_at":"2015-05-10T02:32:07Z","updated_at":"2015-05-10T02:32:07Z","body":"**TL;DR;** I like promises, but I understand it would take a lot of work to switch to promises, so feel free to leave the issue closed.\r\n\r\nI find promises to be very convenient for handling async operations. The most common use cases in which promises provide significant advantage over callbacks are combination, chaining, and error handling.\r\n\r\nLet's say I want to fire off 10 Datastore queries, and then do something when they are all done.\r\nWith callbacks I would have to write a bunch of code to track when each query is complete. With promises I can combine all of the promises returned by each individual query into a single promise which will be resolved when all of the queries are done. All it takes is a single function call.\r\n\r\nPromise chaining allows you to break down sequential async operations which depend on each other's return values, without having to resort to nesting of callbacks. This leads to a more readable and testable code.\r\n\r\nPromises also allow the user of your API to write less code, and have more flexibility. For example, with callbacks I constantly have to check whether an error happened, and can't have a single error handler for multiple related operations. \r\n\r\n**Callbacks**\r\n```js\r\ndataset.save({key: blogPostKey, data: blogPostData}, function(err, response) {\r\n  // Handle error in step 1.\r\n  if (err) {\r\n    return;\r\n  }\r\n\r\n  dataset.save({key: blogPostKey, data: {isDraft: false}}, function(err, response) {\r\n    // Handle error in step 1.\r\n    if (err) {\r\n      return;\r\n    }\r\n\r\n    // Do something on success.\r\n  });  \r\n});\r\n```\r\n\r\n**Promises**\r\n```js\r\ndataset.save({key: blogPostKey, data: blogPostData})\r\n    .then(function(response) {\r\n      return dataset.save({key: blogPostKey, data: {isDraft: false}});\r\n    })\r\n    .then(function(response) {\r\n      // Do something on success.\r\n    })\r\n    .catch(function(err) {\r\n      // Handle errors from step 1 or 2.\r\n    });\r\n```\r\n\r\nQ (https://github.com/kriskowal/q) provides much more detailed comparison of callbacks and promises, and I know of several Node packages that use it. I'm no Node expert, but it seems to me Promises are a pattern that is not language or environment specific.\r\n\r\nSorry for going on and on :) Have a great weekend!"}}