detectCollision
functionSee the Pen Class 3 Challenge - detectCollision() by Liz Shaw (@anythingcodes) on CodePen.
detectCollision
works as intended, we can refactor it to improve its performance and readability. Reformat detectCollision
to use destructuring and an array helper.
Hint: We'll return a single matched object. Which array helper would be best in this case?
const node = {
location: {
start: {
line: 1, // first
column: 1 // second
},
end: {
line: 1,
column: 4
}
},
range: [0, 3] // third: outputs first array element
};
const {
location: { start },
range: [ index ]
} = node;
console.log(start.line); // 1
console.log(start.column); // 1
console.log(index); // 0
What would the following output to the console and why?
Answer:
1
1
0
resolve
and reject
argumentsresolve()
and reject()
are invoked depending on certain conditionsthen()
and catch()
blocks attached to the Promise objectconst promise = new Promise((resolve, reject) => {
});
const promise = new Promise((resolve, reject) => {
});
promise.then(() => {
console.log('my resolution message');
});
const promise = new Promise((resolve, reject) => {
});
promise.then(() => {
console.log('my resolution message');
});
promise.catch(() => {
console.log('my rejection message');
});
const promise = new Promise((resolve, reject) => {
resolve(); // outputs 'my resolution message'
});
promise.then(() => {
console.log('my resolution message');
});
promise.catch(() => {
console.log('my rejection message');
});
const promise = new Promise((resolve, reject) => {
reject(); // outputs 'my rejection message'
});
promise.then(() => {
console.log('my resolution message');
});
promise.catch(() => {
console.log('my rejection message');
});
const promise = new Promise((resolve, reject) => {
resolve(5); // chain callbacks and pass info between them
})
.then((value) => {
console.log(value); // 5
})
.catch(() => {
console.log('my rejection message');
});
Always include a rejection handler! Otherwise your promise may silently fail.
Using Promises
Combine promises in an iterable, such as an array
Promise.all()
waits for all promises in the group to fulfill
Promise.race()
is fulfilled when the fastest promise in the group is fulfilled
The returned promise is fulfilled when all promises in the iterable are fulfilled
Returns an array of result values
If any of the promises in the array fail, the returned promise fails too
See the Pen Promise.all() by Liz Shaw (@anythingcodes) on CodePen.
Instead of waiting for all promises to be fulfilled like in Promise.all()
, a promise using Promise.race()
is fulfilled as soon as any promise in the array is fulfilled
See the Pen Promise.race() by Liz Shaw (@anythingcodes) on CodePen.
function request(url) {
return new Promise((resolve, reject) => {
var xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.onload = function() {
if (this.status >= 200 && this.status < 300) {
resolve(JSON.parse(xhr.response));
} else {
reject({
status: this.status,
statusText: xhr.statusText
});
}
};
xhr.onerror = function() {
reject({
status: this.status,
statusText: xhr.statusText
});
};
xhr.send();
});
}
request('http://json.com'); // returns a promise
The fetch()
helper returns a promise and is used for HTTP requests
The initial return value is the Response object; use chaining and the .json()
method to get the JSON you need
fetch('http://json.com')
.then(serverResponse => serverResponse.json())
.then(json => console.log(json))
.catch(err => console.log(err));
Using the Fetch Helper
See the Pen Fetch Activity by Liz Shaw (@anythingcodes) on CodePen.
When there's a distinct transition, e.g. when you're awaiting a response from an external service
When you need to save your place within a function and get back to that specific place later
When you need to pause execution while you get data elsewhere or run some other code
Say we want to run some errands at three stores: the grocery store, hardware store, and a cafe. Each time we enter a store, we'll spend time retrieving items.
Each time we visit a store, time passes until we yield
some items, then pick up where we left off in our shopping trip
*
) between function
and its name:
function *createIterator() {
// generator function body here
}
// generator functions are called like regular functions but return an iterator
const iterator = createIterator();
yield
keyword specifies the value to be returned with each iterationfunction *createIterator() {
yield 30;
yield 31;
yield 32;
}
yield
value, call yourIterator.next()
to return an object formatted like { value: yieldValue, done: trueOrFalse}
function *createIterator() {
yield 30;
yield 31;
yield 32;
}
const iterator = createIterator();
console.log(iterator.next()); // { value: 30, done: false }
console.log(iterator.next()); // { value: 31, done: false }
console.log(iterator.next()); // { value: 32, done: false }
// subsequent calls
console.log(iterator.next()); // { value: undefined, done: true }
function copyFile (source, dest, callback) {
fs.exists(source, function (exists) {
if (!exists) return callback('Source does not exist')
fs.exists(dest, function (exists) {
if (exists) return callback('Dest already exists')
fs.readFile(source, function (err, data) {
if (err) return callback(err)
fs.writeFile(dest, data, function (err) {
return callback(err)
})
})
})
})
}
const copyFile = watt(function *(source, dest, next) {
if (!(yield fs.exists(source, next.arg(0)))) throw 'Source does not exist'
if (yield fs.exists(dest, next.arg(0))) throw 'Dest already exists'
var data = yield fs.readFile(source, next)
yield fs.writeFile(dest, data, next)
})
Source: watt
library »
Let's take a look »
By default, objects you create are not iterable
Make them iterable with a [Symbol.iterator]
property containing a generator function and for-of
loop:
const team = {
members: ['Sam', 'Tam', 'Lam'],
[Symbol.iterator]: function *(){
for (let member of this.members) {
yield member;
}
}
};
Use concise object methods to trim it down further:
const team = {
members: ['Sam', 'Tam', 'Lam'],
*[Symbol.iterator](){
for (let member of this.members) {
yield member;
}
}
};
Parent and child nodes
Set: An ordered list of unique values. Allows fast access to the data it contains.
const set = new Set([1, 2, 3, 4, 5, 5, 5, 5]);
console.log(set.size); // 5
set.add(6);
console.log(set.size); // 6
Map: An ordered list of key-value pairs, where the key and value can be any type.
const map = new Map();
map.set('title', 'JS206: Intro to ES6');
map.set('group', 'GDI');
console.log(map.get('title')); // JS206: Intro to ES6
console.log(map.get('group')); // GDI
keys()
returns an iterator whose values are the keys contained in the collectionentries()
returns an iterator whose values are key-value pairsvalues()
returns an iterator whose values are the values of the collectionSee the Pen Built-in iterators for Sets, Maps, and objects in ES6 by Liz Shaw (@anythingcodes) on CodePen.
function Vehicle(type) {
this.type = type;
}
Vehicle.prototype.logType = function() {
console.log(this.type);
};
var car = new Vehicle('car');
car.logType(); // 'car'
console.log(car instanceof Vehicle); // true
console.log(car instanceof Object); // true
called "creating a custom type"
class Vehicle {
constructor(type) {
this.type = type;
}
logType() {
console.log(this.type);
}
}
const car = new Vehicle('car');
car.logType(); // 'car'
console.log(car instanceof Vehicle); // true
console.log(car instanceof Object); // true
You don't need commas between the elements of a class
Derived classes: Classes that inherit from other classes
Within the derived class's class {}
definition, use the extends
keyword to specify the base class. Then access the base class constructor by calling super()
.
class Rectangle {
constructor(length, width) {
this.length = length;
this.width = width;
}
getArea() {
return this.length * this.width;
}
}
class Square extends Rectangle {
constructor(length) {
super(length, length); // calls the base class constructor
}
}
const square = new Square(5);
console.log(square.getArea()); // 25
Classes and Derived Classes
See the Pen Shop Activity - Classes and Derived Classes by Liz Shaw (@anythingcodes) on CodePen.
View SolutionJavaScript has an error-prone share everything approach to loading code
Modules are individual files that package and encapsulate individual pieces of functionality (variables, functions, and classes)
Export and import only the bindings you need rather than everything in a file
🌟 No more global scope pollution!
export
keyword before elements you'd like to expose in a file// myExports.js
// export variables
export let description = 'GDI Fan';
export const threshold = 7;
// export functions
export function multiply(a, b) {
return a * b;
}
// export classes
export class Rectangle {
constructor(length, width) {
this.length = length;
this.width = width;
}
}
// private to the module
function sum(a, b) {
return a + b;
}
import
keywordimport
statement requires:
import
statements at the top of a file// index.js
import { Rectangle, description, multiply } from './myExports.js';
const shape = new Rectangle(6, 8);
console.log(description); // 'GDI Fan'
console.log(multiply(3, 5)); // 15
node -v
in your favorite command line tool (such as Terminal or X11 on a Mac, or cmd or Git Bash on Windows).