談談JavaScript非同步操作Promise

左岸16發表於2017-11-16

Promise是一個建構函式

var p = new Promise(function(resolve, reject) {
    // 非同步操作
    setTimeout(function() {
        console.log('success');
        resolve('async data');
    }, 2000);
}).then((data) => {
    console.log(data);
});

執行程式碼,會在2秒後輸出“success”和“async data”。注意!我只是new了一個物件,並沒有呼叫它,我們傳進去的函式就已經執行了,這是需要注意的一個細節。所以我們用Promise的時候一般是包在一個函式中,在需要的時候去執行這個函式。

function runAsync() {
    var p = new Promise(function(resolve, reject) {
        // 非同步操作
        setTimeout(function() {
            console.log('success');
            resolve('async data');
        }, 2000);
    }).then((data) => {
        console.log(data);
    });
    return p;
}

runAsync();

Promise建構函式之後仍然返回一個Promise物件,呼叫then方法,then()接收一個函式型別的引數,並且會拿到在呼叫resolve方法傳遞的資料。then()其實就跟我們平時說的回撥函式是同一個意思,在非同步操作之後被執行。這就是Promise的作用了,簡單來講,就是能把原來的回撥寫法分離出來,在非同步操作執行完後,用鏈式呼叫的方式執行回撥函式。

Promise的優勢在於,可以在then方法中繼續寫Promise物件並返回,然後繼續呼叫then來進行回撥操作。

function runAsync() {
    var p = new Promise(function(resolve, reject) {
        // 非同步操作
        setTimeout(function() {
            console.log('success');
            resolve('async data');
        }, 2000);
    })
    return p;
}

runAsync().then((data) => {
    console.log('successed result: ' + data);
});

執行這個js檔案,在2秒後輸出”success” 和”successed result: async data”。

在then方法中,你也可以直接return資料而不是Promise物件,在後面的then中就可以接收到資料了。

function runAsync1() {
    var p = new Promise(function(resolve, reject) {
        setTimeout(function() {
            console.log('async task 1 success');
            resolve('output data1');
        }, 2000);
    });
    return p;
}

function runAsync2() {
    var p = new Promise(function(resolve, reject) {
        setTimeout(function() {
            console.log('async task 2 success');
            resolve('output data2');
        }, 2000);
    });
    return p;
}

function runAsync3() {
    var p = new Promise(function(resolve, reject) {
        setTimeout(function() {
            console.log('async task 3 success');
            resolve('output data3');
        }, 2000);
    });
    return p;
}

runAsync1().then(function(data) {
    console.log(data);
    return runAsync2();
}).then(function(data) {
    console.log(data);
    return 'return a string not a promise!'
}).then(function(data) {
    console.log(data);
});

輸出結果:

async task 1 success
output data1
async task 2 success
output data2
return a string not a promise!

失敗的回撥函式reject和resolve類似,傳遞一個引數,當執行失敗時將對應的資料傳遞過去。

Promise.all

function resolve(millis, value) {
    return new Promise(resolve => setTimeout(() => resolve(value), millis));
}
Promise.all([
    resolve(5000, 1),
    resolve(6000, 2),
    { hello: 3}
 ]).then(values => console.log(values));
 // [1, 2, { hello: 3 }]

相關文章