4. jsonp&throttle&debounce

86 阅读1分钟
// 手写jsonp
// 节流throttle
// 防抖 debounce
function jsonp({url, params, cb}) {
    return new Promise(resolve => {
        const script = document.createElement("script");
        window[cb] = function(data) {
            resolve(data);
            document.body.removeChild(script);
        }
        params = {...params, cb};
        let arrs = [];
        for(let key in params) {
            arrs.push(`${key}=${params[key]}`)
        }
        script.src = `${url}?${arrs.join("&")}`;
        document.appendChild(script);
    })
}

function throttle(fn , wait, options) {
    let args, context, previous, timeout;
    previous = 0;
    let later = function() {
        previous = options.leading === false ? 0 : Date.now();
        fn.apply(context, args);
    }
    let throttle =  function() {
        args = arguments;
        context = this;
        const now = Date.now();
        if(!previous &&  options.leading === false) {
            previous = now;
        }
        const remaining = wait -  (now - previous);
        if(remaining <= 0) {
            if(timeout) {
                clearTimeout(timeout);
                timeout =  null;
            }
            fn.apply(this, arguments);
            previous = now;
        }else if(!timeout && options.trailing !== false) {
            timeout = setTimeout(later, remaining);
        }
        return throttle;
    }
}

function debounce(fn, wait, immediate) {
    let timeout;
    return function() {
        if(timeout) {
            clearTimeout(timeout);
        }
        if(immediate) {
            let callNow = !timeout;
            if(callNow){
                fn.apply(this, arguments);
            }
        }
        timeout = setTimeout(() => {
            fn.apply(this, arguments);
            timeout = null;
        }, wait)
    }
}


function asyncAdd(a,b,callback) {
    setTimeout(() =>  {
        callback(null, a+b);
    }, 1000)
}

function sumT(a,b) {
    return new Promise((resolve, reject) => {
        asyncAdd(a,b, (err, data) => {
            if(err) reject(err);
            resolve(data);
        })
    })
}

function sum(...args)  {
    return new Promise(resolve => {
        args.reduce((ov,current) => {
            return ov.then(total => sumT(total, current))
        }, Promise.resolve(0)).then(resolve)
    }) 
}

async function sum(...args) {
    if(args.length === 1) return args[0]
    let result = [];
    for(let i = 0; i < args.length; i+=2) {
        result.push(sumT(args[i], args[i+1]))
    }
    if(args.length % 2) {
        result.push(args[args.length - 1])
    }
    return sum(...Promise.all(result))
}