JavaScript・異歩のPromise

5154 ワード

前に書く
本文の内容とコードは廖雪峰先生のJavaScript教程から取っています.この文章は個人のノートとしてのみ、練習コードとして使用されています.関連知識は原文を読んでください.Promise-JavaScript教程
Promise
promiseは非同期プログラミングの解決策で、従来の解決策のcalbackよりも優雅です.promiseは「地獄に戻る」ことを避けました.
実現する需要:関数実行、1 s後にpendingを出力し、2 s後にfinishedを出力します.
  • calback方式:
  • (function print() {
        setTimeout(function(){
            console.log('pending');
            setTimeout(function(){
                console.log('finished');
            },1000)
        },1000)
    })()
  • promise方式:
  • function createPromise() {
        return new Promise(function(resolve,reject){
            setTimeout(resolve,1000)
        });
    }
    
    createPromise().then(function(){
        console.log('pending');
        return createPromise();
    }).then(function(){
        console.log('finished');
    })
  • ps:promiseを使って犯しやすいエラーです.
    let waitSecond = new Promise(function (resolve,reject){
        setTimeout(resolve,1000)
    });
    waitSecond.then(function(){
        console.log('pending');
        return waitSecond;
    }).then(function(){
        console.log('finished');
    })
    // 1  ,       'pending' 'finished'
    //        promise        
    このように見て、promiseの実現はもっと複雑なようです.しかし、シーンが複雑化すれば、test 1を要求し、要求結果をパラメータとしてtest 2を要求し、これを類推する.
    function request(url, param, successFun, errorFun) {
        $.ajax({
            type: 'GET',
            url: url,
            param: param,
            async: true,    //   true,     ;false     
            success: successFun,
            error: errorFun
        });
    }
  • calback方式(ステップajax要求)
  • request('test1.html', '', function(data1) {
        console.log('       ,        :', data1);
        request('test2.html', data1, function (data2) {
            console.log('       ,        :', data2);
            request('test3.html', data2, function (data3) {
                console.log('       ,        :', data3);
                //request...     
            }, function(error3) {
                console.log('       ,       :', error3);
            });
        }, function(error2) {
            console.log('       ,       :', error2);
        });
    }, function(error1) {
        console.log('       ,       :', error1);
    });
  • promise方式(ステップajax要求)
  • function sendRequest(url, param) {
        return new Promise(function(resolve, reject) {
            request(url, param, resolve, reject);
        });
    }
    
    sendRequest('test1.html', '').then(function(data1) {
        console.log('       ,        :', data1);
        return sendRequest('test2.html', data1);
    }).then(function(data2) {
        console.log('       ,        :', data2);
        return sendRequest('test3.html', data2);
    }).then(function(data3) {
        console.log('       ,        :', data3);
    }).catch(function(error) {
        // catch       
        console.log('sorry,      ,       :', error);
    });
    promise練習(setTimeout、DOM操作などを結合する)
  • は1つの0-2の間の乱数を生成し、1より大きい場合、対応する時間を待って成功に戻ります.さもなければ失敗に戻ります.
  • //       log:
    var logging = document.getElementById('log-text');
    while(logging.children.length > 0) {
        logging.removeChild(logging.children[logging.children.length - 1]);
    }
    //        :
    function log(text) {
        var p = document.createElement('p');
        p.innerText = text;
        logging.appendChild(p);
    }
    //   promise   
    new Promise((resolve,reject) => {
        var timeOut = Math.random() * 2;
        log('timeOut:' + timeOut);
        if (timeOut > 1) {
            //       
            setTimeout(resolve,timeOut * 1000,'200 OK');
        } else {
            //       
            setTimeout(() => {
                // log('do something');
                reject('setTimeout is: ' + timeOut )
            },timeOut * 1000);
            //   :         ,   resolve、reject      
        }
    }).then((result) => {
        log('  :' + result);
    }).catch((reason) => {
        log('  :' + reason);
    })
  • シリアルで一連の非同期計算を実行すると、結果を得るタスクが必要になります.例えば、先行平方を実行して、合計を求めて、再平方:
  • //       log:
    var logging = document.getElementById('log-text');
    while(logging.children.length > 0) {
        logging.removeChild(logging.children[logging.children.length - 1]);
    }
    //        :
    function log(text) {
        var p = document.createElement('p');
        p.innerText = text;
        logging.appendChild(p);
    }
    //   promise     
    function multiply(input) {
        return new Promise((resolve,reject) => {
            log('Call multiply(): ');
            log('Calculate ' + input + ' x ' + input);
            setTimeout(resolve,1000,input * input);
        })
    } 
    //   promise     
    function sum(input) {
        return new Promise((resolve,reject) => {
            log('Call sum(): ');
            log('Calculate ' + input + ' + ' + input);
            setTimeout(resolve,1000,input + input);
        })
    }
    new Promise((resolve,reject) => {
        log('start new Promise...');
        resolve(123);
    }).then(multiply)
      .then(sum)
      .then(multiply)
      .then(sum)
      .then((result) => {
          log('The result is: ' + result)
      })