Permalink
Browse files

Merge branch '017/master'

  • Loading branch information...
MicFin committed May 15, 2017
2 parents e254bc3 + e9aa337 commit e140e58c1881088760e812d52655949b091cbd5c
126 README.md
@@ -53,85 +53,151 @@ Promises offer several advantages over callbacks.
- Promises are easier to read than callbacks.
- Promises can simplify error handling.

<!-- start code block file="snippets/readJSON.js" -->
```js
// remember that callback is something you write, in this case to perform some
// processing on parsed JSON
const readJSON = function (filename, callback){
fs.readFile(filename, 'utf8', function (err, res){
const readJSON = function (filename, callback) {
fs.readFile(filename, 'utf8', function (err, res) {
if (err) {
return callback(err); // what's going on here?
return callback(err) // what's going on here?
}
callback(null, JSON.parse(res)); // what if JSON.parse errors out?
});
};
callback(null, JSON.parse(res)) // what if JSON.parse errors out?
})
}
```
<!-- end code block -->

What are some weaknesses in this code? And the following?

<!-- start code block file="snippets/readJSON-1.js" -->
```js
const readJSON = function (filename, callback){ // 👀 here
fs.readFile(filename, 'utf8', function (err, res){
const readJSON = function (filename, callback) { // 👀 here
fs.readFile(filename, 'utf8', function (err, res) {
if (err) {
return callback(err); // pass the error from readFile
return callback(err) // pass the error from readFile
}
try {
res = JSON.parse(res);
res = JSON.parse(res)
} catch (ex) {
return callback(ex); // pass the error from JSON.parse
return callback(ex) // pass the error from JSON.parse
}
callback(null, res); // don't pass the error, since we should have caught it
});
};
callback(null, res) // don't pass the error, since we should have caught it
})
}
```
<!-- end code block -->

What about this instead?

<!-- start code block file="snippets/readJSON-promise.js" -->
```js
const readJSON = function (filename) { // <-- look here
return new Promise((resolve, reject) => {
fs.readFile(filename, { encoding: 'utf8' }, (err, res) => {
if (err) {
reject(err);
reject(err)
} else {
resolve(res);
resolve(res)
}
});
})
})
.then((res) => {
return JSON.parse(res)
});
};
})
}
readJSON('./example.json')
.then((pojo) => {
callback(pojo); // do something with the object
modifierFunc(pojo) // modify object
return pojo // explicitly returns pojo
})
.catch((err) => { // handle error conditions
console.error(err);
});
console.error(err)
})
```
<!-- end code block -->

That's too verbose. This is better:

<!-- start code block file="snippets/readJSON-promise-1.js" -->
```js
const readJSON = function (filename) {
return new Promise((resolve, reject) => {
fs.readFile(filename, { encoding: 'utf8' }, (err, res) => {
if (err) {
reject(err);
reject(err)
} else {
resolve(res);
resolve(res)
}
});
})
})
.then(JSON.parse); // what can we surmise about .then?
};
.then(JSON.parse) // what can we surmise about .then?
}
readJSON('./example.json')
.then(callback) // do something with the object
.catch(console.error); // handle error conditions
.then(modifierFunc) // modify object --> returns what callback(prev) returns
.catch(console.error) // handle error conditions
```
<!-- end code block -->

## Rules for Promisifying Your Code:
#### 1. Only ever pass a function as a call back. NEVER pass a function invocation!
<details>
<summary>Why?</summary>
The difference is `.then()` _expects_ a callback. If you invoke the function, the `.then` gets a _value_ NOT a function to invoke later.
</details>

<!-- start code block file="snippets/callback-vs-invocation.js" -->
```js
.then(JSON.parse)
// vs
.then(JSON.parse(json))
```
<!-- end code block -->

#### 2. ALWAYS consider WHAT is being return from each block of a promise chain. Be explicit if you need to!
<details>
<summary>Why?</summary>
Because some methods don't return what you expect them to. If you're ever unsure, BE SURE by making it explicit!
</details>

#### 3. Safety third
<details>
<summary>Why?</summary>
'cause it should never be first or second.
</details>

#### 4. Indent once at the start, and then lineup your `.then`s and `.catch`s
<details>
<summary>Why?</summary>
Because formatting is important to humans.
</details>

<!-- start code block file="snippets/format.js" -->
```js
startingFunction()
.then(JSON.parse)
.catch(console.error)
```
<!-- end code block -->

#### 5. Never nest `.then`s--return out, and continue with the next `.then` in-line. Why? Because nesting `.then`s defeats the purpose of promises.

<!-- start code block file="snippets/nesting.js" -->
```js
startingFunction()
.then(JSON.parse)
.then((pojo) => {
functionThatReturnsAPromise(pojo)
.then(dontDoThis!) // <-- creates promise hell!
})
.then(doThisInstead!) // <-- narrowly avoids promise hell!
.catch(console.error)
```
<!-- end code block -->


### Code-Along: Promisify `copy-json.js`

@@ -3,7 +3,8 @@
"all": [
"bin/**/*.js",
"lib/**/*.js",
"spec/**/*.spec.js"
"spec/**/*.spec.js",
"snippets/**/*.js"
],
"spec": [
"spec/**/*.spec.js"
@@ -0,0 +1,3 @@
.then(JSON.parse)
// vs
.then(JSON.parse(json))
@@ -0,0 +1,3 @@
startingFunction()
.then(JSON.parse)
.catch(console.error)
@@ -0,0 +1,8 @@
startingFunction()
.then(JSON.parse)
.then((pojo) => {
functionThatReturnsAPromise(pojo)
.then(dontDoThis!) // <-- creates promise hell!
})
.then(doThisInstead!) // <-- narrowly avoids promise hell!
.catch(console.error)
@@ -0,0 +1,13 @@
const readJSON = function (filename, callback) { // 👀 here
fs.readFile(filename, 'utf8', function (err, res) {
if (err) {
return callback(err) // pass the error from readFile
}
try {
res = JSON.parse(res)
} catch (ex) {
return callback(ex) // pass the error from JSON.parse
}
callback(null, res) // don't pass the error, since we should have caught it
})
}
@@ -0,0 +1,16 @@
const readJSON = function (filename) {
return new Promise((resolve, reject) => {
fs.readFile(filename, { encoding: 'utf8' }, (err, res) => {
if (err) {
reject(err)
} else {
resolve(res)
}
})
})
.then(JSON.parse) // what can we surmise about .then?
}

readJSON('./example.json')
.then(modifierFunc) // modify object --> returns what callback(prev) returns
.catch(console.error) // handle error conditions
@@ -0,0 +1,23 @@
const readJSON = function (filename) { // <-- look here
return new Promise((resolve, reject) => {
fs.readFile(filename, { encoding: 'utf8' }, (err, res) => {
if (err) {
reject(err)
} else {
resolve(res)
}
})
})
.then((res) => {
return JSON.parse(res)
})
}

readJSON('./example.json')
.then((pojo) => {
modifierFunc(pojo) // modify object
return pojo // explicitly returns pojo
})
.catch((err) => { // handle error conditions
console.error(err)
})
@@ -0,0 +1,11 @@
// remember that callback is something you write, in this case to perform some
// processing on parsed JSON

const readJSON = function (filename, callback) {
fs.readFile(filename, 'utf8', function (err, res) {
if (err) {
return callback(err) // what's going on here?
}
callback(null, JSON.parse(res)) // what if JSON.parse errors out?
})
}

0 comments on commit e140e58

Please sign in to comment.