当前位置: 首頁 > javascript > promise实现requireJS式加载

promise实现requireJS式加载

最近一直接触到ES6的promise方法,不管是工作上还是面试的时候。

在之前工作上经常会遇到函数深度callback的问题。

promise好像就是为了这种情况而生。以下是原理图。

当前Promise执行完毕之后根据执行成功与否,执行fullfill(resolve)或者reject(error)抛出错误,并return Promise对象并可以用Promise的then方法实现链式调用。

以下是简化的MDN上的例子

'use strict';
    var promiseCount = 0;
    function testPromise() {
        var thisPromiseCount = ++promiseCount;
        var log = document.getElementById('log');
        //console.log('Sync code started');
        var p1 = new Promise(
                function(resolve, reject) {
                    console.log('Async code started');

                    window.setTimeout(
                            function() {
                                // We fulfill the promise !
                                resolve(thisPromiseCount);
                            }, Math.random() * 2000 + 1000);
                }
        );

        p1.then(
                function(val) {
                    console.log(val);
                    console.log('Async code terminated');
                })
                .catch(
                function(reason) {
                    console.log('Handle rejected promise ('+reason+') here.');
                });

        //console.log('Sync code terminated');
    }


    

then方法会根据调用顺序执行,实现Promise过程。

另外Promise对象还有all和rece方法可以使用,

可以对Promise对象调用all(指定Promise对象执行完毕后调用),race(指定Promise对象第一个执行完毕后调用)

var p1 = Promise.resolve(3);
var p2 = 1337;
var p3 = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, "foo");}); 
Promise.all([p1, p2, p3]).then(values => { 
  console.log(values); // [3, 1337, "foo"] });

Promise.race([p1, p2]).then(function(value) {
  console.log(value);        
}, function(reason) {
});


那么,Promise对象其实就是执行完毕后回调,以及按顺序执行then方法的函数参数功能。

可以简化深层callback函数的写法。

MDN上有一个Promise和AJAX结合的例子,以下照搬。

'use strict';

    // A-> $http function is implemented in order to follow the standard Adapter pattern
    function $http(url){

        // A small example of object
        var core = {

            // Method that performs the ajax request
            ajax: function (method, url, args) {

                // Creating a promise
                var promise = new Promise( function (resolve, reject) {

                    // Instantiates the XMLHttpRequest
                    var client = new XMLHttpRequest();
                    var uri = url;

                    if (args && (method === 'POST' || method === 'PUT')) {
                        uri += '?';
                        var argcount = 0;
                        for (var key in args) {
                            if (args.hasOwnProperty(key)) {
                                if (argcount++) {
                                    uri += '&';
                                }
                                uri += encodeURIComponent(key) + '=' + encodeURIComponent(args[key]);
                            }
                        }
                    }

                    client.open(method, uri);
                    client.send();

                    client.onload = function () {
                        if (this.status >= 200 && this.status < 300) {
                            // Performs the function "resolve" when this.status is equal to 2xx
                            resolve(this.response);
                        } else {
                            // Performs the function "reject" when this.status is different than 2xx
                            console.log(this.statusText)
                            reject(this.statusText);

                        }
                    };
                    client.onerror = function () {
                        reject(this.statusText);
                    };
                });

                // Return the promise
                return promise;
            }
        };

        // Adapter pattern
        return {
            'get': function(args) {
                return core.ajax('GET', url, args);
            },
            'post': function(args) {
                return core.ajax('POST', url, args);
            },
            'put': function(args) {
                return core.ajax('PUT', url, args);
            },
            'delete': function(args) {
                return core.ajax('DELETE', url, args);
            }
        };
    };
    // End A

    // B-> Here you define its functions and its payload
    var mdnAPI = 'http://localhost:63342/logo.png';
    var payload = {
        'topic' : 'js',
        'q'     : 'Promise'
    };

    var callback = {
        success: function(data) {
            console.log(1, 'success', JSON.parse(data));
        },
        error: function(data) {
            console.log(2, 'error', JSON.parse(data));
        }
    };
    // End B

    // Executes the method call
    $http(mdnAPI)
            .get(payload)
            .then(callback.success)
            .catch(callback.error);

    // Executes the method call but an alternative way (1) to handle Promise Reject case
    $http(mdnAPI)
            .get(payload)
            .then(callback.success, callback.error);

    // Executes the method call but an alternative way (2) to handle Promise Reject case
    $http(mdnAPI)
            .get(payload)
            .then(callback.success)
            .then(undefined, callback.error);


根据例子,我想到Promise可以实现类似requireJS的文件加载方式。

var obj={};
    obj.p=new Promise(function(resolve){
        resolve("Success!");
    });
    obj.load=function(fileList,i){
        i=i||0;
        if(fileList.length>i){
            var http=new XMLHttpRequest('get',fileList[i]);
            http.open('get',fileList[i]);
            http.send();
            http.onload=function(){

                obj.p.then(function(value){
                    console.log(fileList[--i]+' '+value);
           });

                i++;
                if(fileList.length!=i){
                    obj.load(fileList,i);
                }else{
                    obj.allLoad();
                }
            }
        }
    };
    obj.allLoad=function(){
        Promise.all([obj.p]).then(function(val) {
            console.log(val)
        });
    }
    

obj.load(['VID_20160623_174553.mp4','equip_db.json','logo.png','VID_20160623_174553.mp4','equip_db.json','logo.png']);


一开始我把new Promise放在递归函数里,这样就可以resolve给予递归里的对应参数

(原本这样子做的想法是在调用all方法的时候可以result对应的值,但是其实new Promise后all方法result的值就仅有最后一个)。

后来把new Promise移到外部,以下是执行效果。

评论 ( 0 )

网友留言