異步編程技巧

先看一個例子

var Promise = require("promise-tiny");

new Promise(function(resolve, reject) {    // 注意resolve和reject這兩個參數,實際就是then和catch的參數
        var r = Math.random();
        if(r >= 0.5) resolve('success');
        else reject('fail');
    })
   .then(function(value) {        // >=0.5時,調用這個函數
        console.log(value);
    })
   .catch(function(value) {        // <0.5時,調用這個函數
        console.log(value);
    });

promise-tiny的實現代碼

class Promise {                // 這段代碼主要用於揭示實現原理,對理解異步編程技巧頗有幫助
    constructor(factory) {
        this.flag = 'Pending';        // flag值域 'Pending','Resolved','Rejected'
        this.args = [];
        this.func = {};

        function next(flag, value) {    // next這個函數是精華,factory沒有參數運行起來,全靠它了
            this.flag = flag;
            this.args = [].concat(value);
            this.func[flag] && this.func[flag].apply(undefined, this.args);
        }

        factory(next.bind(this, 'Resolved'), next.bind(this, 'Rejected'));
    }

    then(func) {
        if(this.flag==='Resolved') func.apply(undefined, this.args);
        else this.func['Resolved'] = func;
        return this;
    }

    catch(func) {
        if(this.flag==='Rejected') func.apply(undefined, this.args);
        else this.func['Rejected'] = func;
        return this;
    }
}

理解了原理,就以爲應該能實現的更好。仍是先看一個例子

var Steps = require("promise-tiny/Steps");

class Count {
    constructor() {
        this._step = 0;
    }
    get step() {
        return this._step;
    }
    set step(n) {
        this._step = n;
    }
}

new Steps(new Count)
   .on('Begin', function(next) {
        this.step++;
        next('check', 'Begin');
    })
   .on('check', function(next, ...args) {
        this.step++;
        next('create', [].concat(args, 'check'));
    })
   .on('create', function(next, ...args) {
        this.step++;
        next('error', [].concat(args, 'create'));
    })
   .on('logout', function(next, ...args) {
        this.step++;
        next('End', [].concat(args, 'logout'));
    })
   .on('error', function(next, ...args) {
        this.step++;
        next('End', [].concat(args, 'error'));
    })
   .on('End', function(next, ...args) {
        this.step++;
        console.log('Steps: '+this.step, 'trace: '+[].concat(args, 'End').join('->'));

        next('new Steps', { id: '!Count', count: 0 });
    })
   .on('Begin', function(next, ...args) {
        this.count++;
        next('info', [].concat(args, 'Begin'));
    })
   .on('info', function(next, ...args) {
        this.count++;
        next('logout', [].concat(args, 'info'));
    })
   .on('logout', function(next, ...args) {
        this.count++;
        next('End', [].concat(args, 'logout'));
    })
   .on('error', function(next, ...args) {
        this.count++;
        next('End', [].concat(args, 'error'));
    })
   .on('End', function(next, ...args) {
        this.count++;
        console.log('Count: '+this.count, 'trace: '+[].concat(args, 'End').join('->'), this.id);
    });

結果程序員

Steps: 5 trace: Begin->check->create->error->End
Count: 4 trace: new Steps->Begin->info->logout->End !Count

Promise代碼體會編程

帶有一個函數參數的函數 f1(f2) ,能夠先造一個f2’,這樣就能夠把它執行了 f1(f2’)。promise

這個f2’的功能要這樣實現:當執行到f2’時,f2’要檢查真實的f2是否已經準備好了?若是準備好了,就調用真實的f2;不然,要把調用f2的參數都記下來,等f2準備好時調用。app

這樣就不須要要求調用f1時,f2必須準備好了。但額外要提供一個提交f2的方法。dom

以上就是Promise揭示的異步編程技巧。在Promise中,factory是f1;resolve和reject是f2’;then和catch是提交f2的方法。異步

Promise揭示的編程技巧爲何能改善異步編程方法?異步編程

這主要是由於程序員編寫程序時,老是按照本身的思考習慣和代碼組織習慣編寫程序,偏向於同步執行過程。代碼的提交次序與機器執行次序有着很大差別!Promise揭示的技巧使程序員可以不用考慮機器的執行次序,給點代碼就先執行着,碰到沒給的代碼就記錄下來,等後續代碼提交後接着執行。這樣,程序員只要保證最終把全部代碼都提交就能夠了。函數

應該有更好的實現ui

既然有這樣好的思路,再回頭看看Promise的實現,其中缺陷不言而喻。Steps是一次嘗試,考慮的問題要比Promise多一些。this

相關文章
相關標籤/搜索