破滅のピラミッド
酷すぎるコードで書かれたウェブスパイダ
const request = require('request')
const fs = require('fs')
const mkdirp = require('mkdirp')
const path = require('path')
const utilities = require('./utilities')
function spider(url, callback) {
const filename = utilities.urlToFilename(url)
// ファイルがダウンロード済みかチェック
fs.exists(filename, exists => {
// ファイルが見つからなかった場合、URLをダウンロード
if (!exists) {
console.log(`Downloading ${url}`)
request(url, (err, response, body) => {
if (err) {
callback(err)
} else {
// ファイルを保存するためのディレクトリを作成
mkdirp(path.dirname(filename), err => {
if (err) {
callback(err)
} else {
// HTTPレスポンスのボディをファイルに保存
fs.writeFile(filename, body, err => {
if (err) {
callback(err)
} else {
callback(null, filename, true)
}
})
}
})
}
})
} else {
callback(null, filename, false)
}
})
}
/* -------------------------------------------------------------------------- */
// コマンドラインから受け取ったURLを引数として渡してspiderを呼び出し
spider(process.argv[2], (err, filename, downloaded) => {
if (err) {
console.log(err)
} else if (downloaded) {
console.log(`Completed the download of "${filename}"`)
} else {
console.log(`"${filename}" was already downloaded`)
}
})
// node index <https://tetracalibers.net>
関数分割による逐次処理(決められた順番で実行)
ウェブスパイダの改良
- if文にelse節を書かず、returnなどでなるべく早く抜ける
- コールバックを独立した関数として定義する
- 必要なデータを引数として渡し、クロージャを使わない
- 一つの関数でネストしたコールバックを書かずに複数の関数に分割する
const request = require('request')
const fs = require('fs')
const mkdirp = require('mkdirp')
const path = require('path')
const utilities = require('./utilities')
// ファイルを保存
function saveFile(filename, contents, callback) {
// ファイルを保存するためのディレクトリを作成
mkdirp(path.dirname(filename), err => {
if (err) {
return callback(err)
}
// HTTPレスポンスのボディをファイルに保存
fs.writeFile(filename, contents, callback)
})
}
// URLをダウンロード
function download(url, filename, callback) {
console.log(`Downloading ${url}`)
request(url, (err, response, body) => {
if (err) {
return callback(err)
}
// ファイルを保存
saveFile(filename, body, err => {
if (err) {
return callback(err)
}
console.log(`Downloaded and saved: ${url}`)
callback(null, body)
})
})
}
function spider(url, callback) {
const filename = utilities.urlToFilename(url)
// ファイルがダウンロード済みかチェック
fs.exists(filename, exists => {
if (exists) {
return callback(null, filename, false)
}
// ファイルが見つからなかった場合、URLをダウンロード
download(url, filename, err => {
if (err) {
return callback(err)
}
callback(null, filename, true)
})
})
}
/* -------------------------------------------------------------------------- */
// コマンドラインから受け取ったURLを引数として渡してspiderを呼び出し
spider(process.argv[2], (err, filename, downloaded) => {
if (err) {
console.log(err)
} else if (downloaded) {
console.log(`Completed the download of "${filename}"`)
} else {
console.log(`"${filename}" was already downloaded`)
}
})
// node index <https://tetracalibers.net>