回調地獄


1. 異步操作

var fs = require('fs');

fs.readFile('./views/index.html',  (err, data) => {
    if (err) {
        throw err
    }
    console.log(data.toString());
})

fs.readFile('./views/main.html', (err, data) => {
    if (err) {
        throw err
    }
    console.log(data.toString());
})

fs.readFile('./views/update.html', (err, data) => {
    if (err) {
        throw err
    }
    console.log(data.toString());
})

在異步操作中,由於操作系統分片工作機制,下面三個文件的輸出順序是不確定的,后執行的可能會先輸出。若要保證輸出順序,在前一個異步操作的回調函數中調用后一個異步操作。

var fs = require('fs');

fs.readFile('./views/index.html',  (err, data) => {
    if (err) {
        throw err
    }
    fs.readFile('./views/main.html', (err, data) => {
        if (err) {
            throw err
        }
        fs.readFile('./views/update.html', (err, data) => {
            if (err) {
                throw err
            }
            console.log(data.toString());
        })   
        console.log(data.toString());
    })
    console.log(data.toString());
})

這種情況下便出現了回調地獄。當異步操作越多,這種嵌套的層級也就越復雜,不利於代碼維護。

2. Promise

  • pending: 初始狀態,既不是成功,也不是失敗狀態。
  • fulfilled: 意味着操作成功完成。
  • rejected: 意味着操作失敗。

pending 狀態的 Promise 對象可能會變為fulfilled 狀態並傳遞一個值給相應的狀態處理方法,也可能變為失敗狀態(rejected)並傳遞失敗信息。當其中任一種情況出現時(settled),Promise 對象的 then 方法綁定的處理方法(handlers )就會被調用(then方法包含兩個參數:onfulfilled 和 onrejected,它們都是 Function 類型。當Promise狀態為fulfilled時,調用 then 的 onfulfilled 方法,當Promise狀態為rejected時,調用 then 的 onrejected 方法),將相應的回調函數放入微任務(microtask)中

var p1 = new Promise((resolve, reject) => {
    console.log('before async');
    fs.readFile('./views/index.html', (err, data) => {
        if (err) {
           reject(err);
        }
        console.log('in async')
        resolve(data);
    })
})
console.log('3333');

結果:

// before async
// 3333
// in async

注意:Promise本身只是個容器,不是異步的,其中要完成的任務才是異步的。

p1.then((data) => {
    console.log(data);
}, (err) => {
    console.log('出錯了', err)
})

then方法接受的第一個(函數)參數,對應着生成Promise函數中接收的resolve;第二個(函數)參數,對應着reject.

then方法的執行結果是一個promise。我們可以鏈接任意個then,前一個then的回調結果將作為參數傳遞給下一個then回調!

 

 解決回調地獄的多重嵌套問題——promise鏈式編程

var p1 = new Promise((resolve, reject) => {
    console.log('before async');
    fs.readFile('./views/index.html', (err, data) => {
        if (err) {
            reject(err);
        }
        console.log('in async')
        resolve(data);
    })
})

var p2 = new Promise((resolve, reject) => {
    console.log('before async');
    fs.readFile('./views/update.html', (err, data) => {
        if (err) {
            reject(err);
        }
        console.log('in async')
        resolve(data);
    })
})


p1.then((data) => {
    console.log(data.toString());
// return 返回的結果會在后面緊接着的then方法中被函數接收
// return 123, data就是123;return p2,是一個resolved promise, data接收到的就是resolve包裹的值
    return p2;
}, (err) => {
    console.log('出錯了', err)
}).then((data) => {
    console.log(data);
} )

封裝

function pReadFile(path) {
    return new Promise((resolve, reject) => {
        fs.readFile(path, (err, data) => {
            if (err) {
                reject(err);
            }
            resolve(data);
        })
    })
}

var p1 = pReadFile('./views/index.html');
var p2 = pReadFile('./views/update.html');


p1.then((data) => {
    console.log(data.toString());
    return p2;
}, (err) => {
    console.log('出錯了', err)
}).then((data) => {
    console.log(data.toString());
} )

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM