◆ 私としては コールバックでも別にいいかな

今度は使ってみるです

Promise を返す関数を作る

昔作ってたライブラリの一部を Promise 化してみます
XHR とそれを使って Mime type を取得するものです

function getActualMimeType(url, cb){
XHR(url, "HEAD", xhr => {
cb(xhr.status === 200 ? xhr.getResponseHeader("Content-Type") : null)
}, xhr => {
cb(null)
})
}

function XHR(url, type, headers, cb, cberr){
var xhr = new XMLHttpRequest()
xhr.open(type, url)
xhr.onload = function(){
if(this.readyState == 4){
cb(this);
}
}
xhr.onerror = cberr || function(){}
xhr.ontimeout = cberr || function(){}
if(type.toUpperCase() === "POST"){
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded")
}
headers && headers.forEach((val, key) => xhr.setRequestHeader(key, val))
xhr.send()
}


Promise 化
function getActualMimeType(url){
return new Promise((success, fail) => {
XHR(url, "HEAD").then(xhr => {
if(xhr.status === 200)
success(xhr.getResponseHeader("Content-Type"))
else
return Promise.reject()
}).catch(xhr => {
fail(null)
})
})
}

function XHR(url, type, headers){
return new Promise((success, fail) => {
var xhr = new XMLHttpRequest()
xhr.open(type, url)
xhr.onload = function(){
if(this.readyState == 4){
success(this);
}
}
xhr.onerror = fail
xhr.ontimeout = fail
if(type.toUpperCase() === "POST"){
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded")
}
headers && headers.forEach((val, key) => xhr.setRequestHeader(key, val))
xhr.send()
})
}

Promise のほうが Promise のコンストラクタに渡す関数にする分 ネストが多いです
コールバック渡す方法でも気をつければそこまでコールバック地獄にならないですし 個人的には Promise なくても困らないといえば困らないかなー と思います

Promise を返す関数を使う

それぞれで /1, /2, /3 に順番にアクセスして終わったら end と表示するコードを書いてみるとこうなります
function fn_callback(cb){
start()

function start(){
XHR("/1", "GET", {}, after1, error)
}

function after1(xhr){
XHR("/2", "GET", {}, after2, error)
}

function after2(xhr){
XHR("/3", "GET", {}, cb, error)
}

function error(e){
console.log(e)
cb()
}

}
fn_callback(_ => console.log("end"))


function fn_promise(){
return XHR("/1", "GET", {})
.then(xhr => {
return XHR("/2", "GET", {})
})
.then(xhr => {
return XHR("/3", "GET", {})
})
.catch(e => console.log(e))
}
fn_promise().then(_ => console.log("end"))

使う側になると Promise のほうが書く量が少ないです
それに コールバックを渡さないので 普通の関数の return みたいに返り値を使って書けます

やっぱり私としてはどっちでもいいかなー
さすがにコールバックでこんなコードを書かれたら Promise のほうがいいと思いますけど

ダメなやつ
function fn_callback(cb){
XHR("/1", "GET", {}, function(xhr){
XHR("/2", "GET", {}, function(xhr){
XHR("/3", "GET", {}, cb, function(e){
console.log(e)
cb()
})
}, function(e){
console.log(e)
cb()
})
}, function(e){
console.log(e)
cb()
})
}
fn_callback(_ => console.log("end"))

Object に forEach メソッドを作ってないとエラー出ますのでコピペの際は注意してください