Skip to content
Permalink
Browse files
  • Loading branch information
aa7401 committed Oct 12, 2019
2 parents 23eca50 + 111e500 commit a43b8572eee4399e1a0ff200226af548ae4af0cf
Show file tree
Hide file tree
Showing 12 changed files with 387 additions and 26 deletions.
@@ -2,6 +2,12 @@
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Launch Current Opened File",
"program": "${file}"
},
{
"type": "node",
"request": "launch",
@@ -3,7 +3,9 @@

In this worksheet you will learn how to configure your work environment using VS Code. You should start by installing **Visual Studio Code** (NOT VISUAL STUDIO!) from the [website](https://code.visualstudio.com), note that it might already be installed. If you are using a Coventry University computer and the software is not installed you can do this using AppsAnywhere.

If you are using Windows 10 you will also need to install [Git](https://git-scm.com/download/win), this may already be installed on a Coventry University computer.
If you are using Windows 10 you will also need to install [Git](https://git-scm.com/download/win), this may already be installed on a Coventry University computer. If you are on MacOS you may already have it installed as it comes with the XCode IDE but if you have recently updated your OS you may need to run the `xcode-select --install` command to update the **Xcode Command-line Tools** but if you don't want to install XCode you can install git using [HomeBrew](http://brew.sh/) using the `brew install git` command. If you are running Ubuntu you can install it using the `sudo apt install git` command.

DO NOT INSTALL THE GIT GUI TOOLS!

Visual Studio Code comes with an integrated **Terminal** that can be used instead of the standard _Command Prompt_ or _Terminal_. If you are using Linux or MacOS this will give you a Bash prompt however on Windows 10 it defaults to the _Command Prompt_ and will need to be changed to the _Bash Shell_.

@@ -135,7 +135,16 @@ The callbacks are already nested 3 deep. To test your knowledge of deeply nested

1. modify the script to ask for the currency to convert to and display only the one conversion rate.
2. instead of printing the exchange rate, ask for the amount to be converted and them return the equivalent in the chosen currency
3. use the [OpenExchangeRates](https://openexchangerates.org/api/currencies.json) API to display the full name of the chosen currency.
3. The `currencies.json` file contains a map between the currency code and the country name. Load this file into the script using the [`fs`](https://nodejs.org/api/fs.html) module, convert to a JavaScript object using the [`JSON`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON) object and use it to display the full name of the chosen currency. Below is some code to get you started.

You will need to import the `fs` module and use the `fs.readFile()` function which takes a callback!

```javascript
fs.readFile('currencies.json', 'utf8', (err, contents) => {
if(err) console.log('you need to handle this properly')
console.log(contents)
})
```

Even though the script is still simple you are probably already getting in a tangle! Imagine a more complex script with conditions, it would quickly get out of hand and become practically impossible to debug.

@@ -155,6 +164,7 @@ A promise represents the result of an asynchronous operation. As such it can be

Promises are created using the `new` keyword. This function is called immediately with two arguments. The first argument resolves the promise and the second one rejects it. Once the appropriate argument is called the promise state changes.
```javascript
const url = 'https://api.exchangeratesapi.io/latest?base=GBP'
const getData = url => new Promise( (resolve, reject) => {
request(url, (err, res, body) => {
if (err) reject(new Error('invalid API call'))
@@ -173,7 +183,7 @@ As you can see it it simple to wrap any async callbacks in promises but how are

To use promises we need a mechanism that gets triggered as soon as a promise changes state. A promise includes a `then()` method which gets called if the state changes to _fulfilled_ and a `catch()` method that gets called if the state changes to _rejected_.
```javascript
const aPromise = getData('http://api.fixer.io/latest?base=GBP')
const aPromise = getData('https://api.exchangeratesapi.io/latest?base=GBP')
aPromise.then( data => console.log(data))
@@ -185,7 +195,7 @@ If the state of the promise changes to _rejected_, the `catch()` method is calle

This code can be written in a more concise way by _chaining_ the promise methods.
```javascript
getData('http://api.fixer.io/latest?base=GBP')
getData('https://api.exchangeratesapi.io/latest?base=GBP')
.then( data => console.log(data))
.catch( err => console.error(`error: ${err.message}`))
```
@@ -214,7 +224,7 @@ const exit = () => new Promise( () => {
process.exit()
})
getData('http://api.fixer.io/latest?base=GBP')
getData('https://api.exchangeratesapi.io/latest?base=GBP')
.then( data => printObject(data))
.then( () => exit())
.catch(err => console.error(`error: ${err.message}`))
@@ -229,7 +239,7 @@ Despite the code in the `printObject` promise being _synchronous_ it is better t
If a promise only takes a single parameter and this matches the data passed back when the previous promise _fulfills_ there is a more concise way to write this.

```javascript
getData('http://api.fixer.io/latest?base=GBP')
getData('https://api.exchangeratesapi.io/latest?base=GBP')
.then(printObject)
.then(exit)
.catch(err => console.error(`error: ${err.message}`))
@@ -240,7 +250,7 @@ getData('http://api.fixer.io/latest?base=GBP')
There are some situations where you can't simply pass the output from one promise to the input of the next one. Sometimes you need to store data for use further down the promise chain. This can be achieved by storing the data in the `this` object.

```javascript
getData('http://api.fixer.io/latest?base=GBP')
getData('https://api.exchangeratesapi.io/latest?base=GBP')
.then( data => this.jsonData = data)
.then( () => printObject(this.jsonData))
.then(exit)
@@ -256,9 +266,9 @@ Run the `promises.js` script. Its functionality should be familiar to the `curre

Study the code carefully. Notice that it defines 5 promises and chains them together. You are going to extend the functionality by defining some additional promises and adding them to the promise chain.

1. modify the script to ask for the currency to convert to and display only the one conversion rate.
2. instead of printing the exchange rate, ask for the amount to be converted and them return the equivalent in the chosen currency
3. use the [OpenExchangeRates](https://openexchangerates.org/api/currencies.json) API to display the full name of the chosen currency
1. Modify the script to ask for the currency to convert to and display only the one conversion rate.
2. Instead of printing the exchange rate, ask for the amount to be converted and them return the equivalent in the chosen currency.
3. The `currencies.json` file contains a map between the currency code and the country name. Load this file into the script using the [`fs`](https://nodejs.org/api/fs.html) module, convert to a JavaScript object using the [`JSON`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON) object and use it to display the full name of the chosen currency.

### 6.5 Executing Code Concurrently

@@ -281,7 +291,7 @@ const dataArray = ['USD', 'EUR']
const promiseArray = []
dataArray.forEach( curr => {
promiseArray.push(new Promise( (resolve, reject) => {
const url = `http://api.fixer.io/latest?base=GBP&symbols=${curr}`
const url = `https://api.exchangeratesapi.io/latest?base=GBP&symbols=${curr}`
request.get(url, (err, res, body) => {
if (err) reject(new Error(`could not get conversion rate for ${curr}`))
resolve(body)
@@ -347,7 +357,7 @@ const printObject = data => new Promise( resolve => {
async function main() {
try {
const data = await getData('http://api.fixer.io/latest?base=GBP')
const data = await getData('https://api.exchangeratesapi.io/latest?base=GBP')
await printObject(data)
process.exit()
} catch (err) {
@@ -386,8 +396,8 @@ both `printObjectPromise` and `printObjectAsync` behave in exactly the same mann

Run the `asyncFunctions.js` script, located in the otherScripts folder. Note that it works in the same way as the previous ones. Open the script and study it carefully.

1. modify the script to ask for the currency to convert to and display only the one conversion rate.
2. instead of printing the exchange rate, ask for the amount to be converted and them return the equivalent in the chosen currency
3. use the [OpenExchangeRates](https://openexchangerates.org/api/currencies.json) API to display the full name of the chosen currency
4. rewrite the `printObject` promise as an _async function_.
5. rewrite another promise as an _async function_.
1. Modify the script to ask for the currency to convert to and display only the one conversion rate.
2. Instead of printing the exchange rate, ask for the amount to be converted and them return the equivalent in the chosen currency
3. The `currencies.json` file contains a map between the currency code and the country name. Load this file into the script using the [`fs`](https://nodejs.org/api/fs.html) module, convert to a JavaScript object using the [`JSON`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON) object and use it to display the full name of the chosen currency.
4. Rewrite the `printObject` promise as an _async function_.
5. Rewrite another promise as an _async function_.
@@ -0,0 +1,57 @@

'use strict'

const request = require('request')
const readline = require('readline')

const baseURL = 'https://api.exchangeratesapi.io/latest'

async function main() {
try {
const base = await getInput('enter base currency')
await checkValidCurrencyCode(base)
const data = await getData(`${baseURL}?base=${base}`)
await printObject(data)
const to = await getInput('convert to')
console.log(to)
process.exit()
} catch (err) {
console.log(`error: ${err.message}`)
}
}

const getInput = prompt => new Promise(resolve => {
const read = readline.createInterface({ input: process.stdin, output: process.stdout })
read.question(`${prompt}: `, value => {
console.log(`You entered ${value}`)
read.close()
resolve(value)
})
})

const checkValidCurrencyCode = code => new Promise( (resolve, reject) => {
code = code.trim()
request(baseURL, (err, res, body) => {
if (err) reject(new Error('invalid API call'))
const rates = JSON.parse(body).rates
if (!rates.hasOwnProperty(code)) it.throw(new Error(`invalid currency code ${code}`))
resolve()
})
})

const getData = url => new Promise( (resolve, reject) => {
request(url, (err, res, body) => {
if (err) reject(new Error('invalid API call'))
resolve(body)
})
})

const printObject = data => new Promise( (resolve) => {
const indent = 2
data = JSON.parse(data)
const str = JSON.stringify(data, null, indent)
console.log(str)
resolve()
})

main()
@@ -0,0 +1,173 @@
{
"AED": "United Arab Emirates Dirham",
"AFN": "Afghan Afghani",
"ALL": "Albanian Lek",
"AMD": "Armenian Dram",
"ANG": "Netherlands Antillean Guilder",
"AOA": "Angolan Kwanza",
"ARS": "Argentine Peso",
"AUD": "Australian Dollar",
"AWG": "Aruban Florin",
"AZN": "Azerbaijani Manat",
"BAM": "Bosnia-Herzegovina Convertible Mark",
"BBD": "Barbadian Dollar",
"BDT": "Bangladeshi Taka",
"BGN": "Bulgarian Lev",
"BHD": "Bahraini Dinar",
"BIF": "Burundian Franc",
"BMD": "Bermudan Dollar",
"BND": "Brunei Dollar",
"BOB": "Bolivian Boliviano",
"BRL": "Brazilian Real",
"BSD": "Bahamian Dollar",
"BTC": "Bitcoin",
"BTN": "Bhutanese Ngultrum",
"BWP": "Botswanan Pula",
"BYN": "Belarusian Ruble",
"BZD": "Belize Dollar",
"CAD": "Canadian Dollar",
"CDF": "Congolese Franc",
"CHF": "Swiss Franc",
"CLF": "Chilean Unit of Account (UF)",
"CLP": "Chilean Peso",
"CNH": "Chinese Yuan (Offshore)",
"CNY": "Chinese Yuan",
"COP": "Colombian Peso",
"CRC": "Costa Rican Colón",
"CUC": "Cuban Convertible Peso",
"CUP": "Cuban Peso",
"CVE": "Cape Verdean Escudo",
"CZK": "Czech Republic Koruna",
"DJF": "Djiboutian Franc",
"DKK": "Danish Krone",
"DOP": "Dominican Peso",
"DZD": "Algerian Dinar",
"EGP": "Egyptian Pound",
"ERN": "Eritrean Nakfa",
"ETB": "Ethiopian Birr",
"EUR": "Euro",
"FJD": "Fijian Dollar",
"FKP": "Falkland Islands Pound",
"GBP": "British Pound Sterling",
"GEL": "Georgian Lari",
"GGP": "Guernsey Pound",
"GHS": "Ghanaian Cedi",
"GIP": "Gibraltar Pound",
"GMD": "Gambian Dalasi",
"GNF": "Guinean Franc",
"GTQ": "Guatemalan Quetzal",
"GYD": "Guyanaese Dollar",
"HKD": "Hong Kong Dollar",
"HNL": "Honduran Lempira",
"HRK": "Croatian Kuna",
"HTG": "Haitian Gourde",
"HUF": "Hungarian Forint",
"IDR": "Indonesian Rupiah",
"ILS": "Israeli New Sheqel",
"IMP": "Manx pound",
"INR": "Indian Rupee",
"IQD": "Iraqi Dinar",
"IRR": "Iranian Rial",
"ISK": "Icelandic Króna",
"JEP": "Jersey Pound",
"JMD": "Jamaican Dollar",
"JOD": "Jordanian Dinar",
"JPY": "Japanese Yen",
"KES": "Kenyan Shilling",
"KGS": "Kyrgystani Som",
"KHR": "Cambodian Riel",
"KMF": "Comorian Franc",
"KPW": "North Korean Won",
"KRW": "South Korean Won",
"KWD": "Kuwaiti Dinar",
"KYD": "Cayman Islands Dollar",
"KZT": "Kazakhstani Tenge",
"LAK": "Laotian Kip",
"LBP": "Lebanese Pound",
"LKR": "Sri Lankan Rupee",
"LRD": "Liberian Dollar",
"LSL": "Lesotho Loti",
"LYD": "Libyan Dinar",
"MAD": "Moroccan Dirham",
"MDL": "Moldovan Leu",
"MGA": "Malagasy Ariary",
"MKD": "Macedonian Denar",
"MMK": "Myanma Kyat",
"MNT": "Mongolian Tugrik",
"MOP": "Macanese Pataca",
"MRO": "Mauritanian Ouguiya (pre-2018)",
"MRU": "Mauritanian Ouguiya",
"MUR": "Mauritian Rupee",
"MVR": "Maldivian Rufiyaa",
"MWK": "Malawian Kwacha",
"MXN": "Mexican Peso",
"MYR": "Malaysian Ringgit",
"MZN": "Mozambican Metical",
"NAD": "Namibian Dollar",
"NGN": "Nigerian Naira",
"NIO": "Nicaraguan Córdoba",
"NOK": "Norwegian Krone",
"NPR": "Nepalese Rupee",
"NZD": "New Zealand Dollar",
"OMR": "Omani Rial",
"PAB": "Panamanian Balboa",
"PEN": "Peruvian Nuevo Sol",
"PGK": "Papua New Guinean Kina",
"PHP": "Philippine Peso",
"PKR": "Pakistani Rupee",
"PLN": "Polish Zloty",
"PYG": "Paraguayan Guarani",
"QAR": "Qatari Rial",
"RON": "Romanian Leu",
"RSD": "Serbian Dinar",
"RUB": "Russian Ruble",
"RWF": "Rwandan Franc",
"SAR": "Saudi Riyal",
"SBD": "Solomon Islands Dollar",
"SCR": "Seychellois Rupee",
"SDG": "Sudanese Pound",
"SEK": "Swedish Krona",
"SGD": "Singapore Dollar",
"SHP": "Saint Helena Pound",
"SLL": "Sierra Leonean Leone",
"SOS": "Somali Shilling",
"SRD": "Surinamese Dollar",
"SSP": "South Sudanese Pound",
"STD": "São Tomé and Príncipe Dobra (pre-2018)",
"STN": "São Tomé and Príncipe Dobra",
"SVC": "Salvadoran Colón",
"SYP": "Syrian Pound",
"SZL": "Swazi Lilangeni",
"THB": "Thai Baht",
"TJS": "Tajikistani Somoni",
"TMT": "Turkmenistani Manat",
"TND": "Tunisian Dinar",
"TOP": "Tongan Pa'anga",
"TRY": "Turkish Lira",
"TTD": "Trinidad and Tobago Dollar",
"TWD": "New Taiwan Dollar",
"TZS": "Tanzanian Shilling",
"UAH": "Ukrainian Hryvnia",
"UGX": "Ugandan Shilling",
"USD": "United States Dollar",
"UYU": "Uruguayan Peso",
"UZS": "Uzbekistan Som",
"VEF": "Venezuelan Bolívar Fuerte (Old)",
"VES": "Venezuelan Bolívar Soberano",
"VND": "Vietnamese Dong",
"VUV": "Vanuatu Vatu",
"WST": "Samoan Tala",
"XAF": "CFA Franc BEAC",
"XAG": "Silver Ounce",
"XAU": "Gold Ounce",
"XCD": "East Caribbean Dollar",
"XDR": "Special Drawing Rights",
"XOF": "CFA Franc BCEAO",
"XPD": "Palladium Ounce",
"XPF": "CFP Franc",
"XPT": "Platinum Ounce",
"YER": "Yemeni Rial",
"ZAR": "South African Rand",
"ZMW": "Zambian Kwacha",
"ZWL": "Zimbabwean Dollar"
}
@@ -34,6 +34,9 @@
"koa-static": "^5.0.0",
"koa-views": "^6.1.5",
"mime-types": "^2.1.22",
"readline": "^1.3.0",
"readline-sync": "^1.4.10",
"request": "^2.88.0",
"sqlite-async": "^1.0.11"
},
"devDependencies": {

0 comments on commit a43b857

Please sign in to comment.