在javascript中每15毫秒进行一次API调用

时间:2017-08-07 21:52:27

标签: javascript jquery api

我有3个功能,checkusername(用户名),checkemail(电子邮件),checkpassword(密码)。每个检查的API都有一个速率限制,每次调用之间必须有15毫秒的延迟。我试过了:

setTimeout(checkusername(username), 1500);
setTimeout(checkemail(email), 1500);
setTimeout(checkpassword(password), 1500);

这不起作用。我尝试过各种其他方法,例如使用变量将延迟增加1500:

var delay = 1500;
checkusername(username);
if(delay == 1500) {
    delay = delay + 1500;
    checkemail(email);
}
else if(delay == 3000) {
    delay = delay + 1500;
    checkpassword(password);
}

console.log('Checks done!');

根据HaveIbeenpwned API,控制台中仍然无法获取代码429(超出速率限制)。

使用Javascript或jQuery的答案,或者如果有解决办法,我可以在PHP中尝试吗?

顺便说一句,每个函数都使用jQuery $.ajax({})调用API。

编辑:

function checkusername(username) {
        $.ajax({
            url: 'https://haveibeenpwned.com/api/v2/breachedaccount/'+username+'?includeUnverified=true',
            type: 'GET',
            dataType: 'json',
            success: function(data) {
                var html = '<h4>Your username was found in the following hacked site breaches:</h4>';
                for(i=0;i<data.length;i++) {
                    var breachName = data[i].Title;
                    var breachDesc = data[i].Description
                    html += '<h3><span class="label label-danger">'+breachName+'</span></h3>';
                    html += '<p>'+breachDesc+'</p>';
                    html += '<br>';
                }
                $('#results').append(html);
            }
        });
    }

3 个答案:

答案 0 :(得分:3)

首先,这是一个帮助函数,它将返回一个将在15毫秒内解析的Promise。

function delay15 () {
  return new Promise(function(resolve) { setTimeout(resolve, 15) })
}

您需要撰写checkusernamecheckemail和&amp; checkpassword函数在请求完成时返回Promise。

示例checkusername函数(请注意添加的return语句):

function checkusername(username) {
        return $.ajax({
            url: 'https://haveibeenpwned.com/api/v2/breachedaccount/'+username+'?includeUnverified=true',
            type: 'GET',
            dataType: 'json',
            success: function(data) {
                var html = '<h4>Your username was found in the following hacked site breaches:</h4>';
                for(i=0;i<data.length;i++) {
                    var breachName = data[i].Title;
                    var breachDesc = data[i].Description
                    html += '<h3><span class="label label-danger">'+breachName+'</span></h3>';
                    html += '<p>'+breachDesc+'</p>';
                    html += '<br>';
                }
                $('#results').append(html);
            }
        });
    }

然后你编写类似这样的代码:

checkusername(username)
  .then(delay15)
  .then(function() { return checkemail(email) })
  .then(delay15)
  .then(function() { return checkpassword(password) })

这是ES2015中的相同代码,虽然在浏览器中不太受欢迎,但它更短,但是这个代码更短:

function delay15 () {
  return new Promise(resolve => setTimeout(resolve, 15))
}

checkusername(username)
  .then(delay15)
  .then(() => checkemail(email))
  .then(delay15)
  .then(() => checkpassword(password))

答案 1 :(得分:1)

你的setTimeout方法基本上同时触发所有3个请求,但是在调用setTimeout后1.5秒。尝试将您的请求链接为承诺或回调,这样您就不会同时发送所有请求。

编辑: 这是你的榜样:

function checkUsername(u) {
    return new Promise(function(resolve, reject) {
         //check username
        if (success) {return resolve();}
        else {return reject();}
    }
}

checkUsername('username').then(function() {checkNextThing()});

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

答案 2 :(得分:0)

你现在可能已将它排序了,但是如果你不这样做,那么也许以下的mighht可能会被使用〜似乎终于正常工作了!而不是使用jQuery(我不使用它)或传统的XMLHttpRequest这取决于基于Fetch

概念的新Promises api
<!doctype html>
<html>
    <head>
        <title>Have I been pwned?</title>
        <script>
            var flags={
                capture:false,
                passive:true,
                once:false
            };

            /* Results from each request will be stored here */
            var data={};

            /* Whether or not to return FULL data as response */
            var truncate=false;

            /* Whether or not to include unverified results */
            var verified=false;

            /* A randomly chosen email address & password for testing */
            var username='dave@gmail.com';
            var email='andy@yahoo.com';
            var password='knickers';
            /* No idea who dave@gmail.com or andy@yahoo.com is btw */

            /* Request configuration */
            var config={
                'method':'get',
                'mode':'cors'
            };

            /* Error callback function */
            var evtError=function(err){
                console.info('oops: %s',err.message);
            };
            /* Time to wait */
            const t=1500;

            /* Promise to wait specified time */
            const wait = ms => new Promise( resolve => setTimeout( resolve, ms ) );

            function create( t, a, p ) {
                try{
                    var el = ( typeof( t )=='undefined' || t==null ) ? document.createElement( 'div' ) : document.createElement( t );
                    for( var x in a ) if( a.hasOwnProperty( x ) && x!=='innerHTML' ) el.setAttribute( x, a[ x ] );
                    if( a.hasOwnProperty('innerHTML') ) el.innerHTML=a.innerHTML;
                    if( p!=null ) typeof( p )=='object' ? p.appendChild( el ) : document.getElementById( p ).appendChild( el );
                    return el;
                }catch(err){
                    console.warn('createNode: %s, %o, %o',t,a,p);
                }
            }

            function process( data ){
                if( typeof( data )=='object' ){
                    /* use the data */
                    console.info(data)

                    var div=document.getElementById('results');
                    var _username=data.username;
                    var _email=data.email;
                    var _pwd=data.password;

                    /* Process username pwnage */
                    create('h1',{innerHTML:'Username pwnage for: '+username },div );
                    for( var n in _username ){
                        if( typeof( _username[ n ] ) =='object' ){
                            var keys=Object.keys( _username[ n ] );
                            var values=Object.values( _username[ n ] );

                            keys.forEach(function(e,i,a){
                                create(null,{innerHTML:e+': '+values[i]},div);
                            });
                        }
                    }

                    /* Process email pwnage */
                    create('h1',{innerHTML:'Email pwnage for: '+email },div );
                    for( var n in _email ){
                        if( typeof( _email[ n ] ) =='object' ){
                            var keys=Object.keys( _email[ n ] );
                            var values=Object.values( _email[ n ] );

                            keys.forEach(function(e,i,a){
                                create(null,{innerHTML:e+': '+values[i]},div);
                            });
                        }
                    }

                    /* Finally - password pwnage */
                    create('h1',{innerHTML:'Password pwnage for: '+password },div );
                    create(null,{innerHTML:_pwd},div);
                }
            }

            function pwned( event ){
                var urls={
                    username:'https://haveibeenpwned.com/api/v2/breachedaccount/'+encodeURIComponent( username )+'?truncateResponse='+truncate+'&includeUnverified='+verified,
                    email:'https://haveibeenpwned.com/api/v2/breachedaccount/'+encodeURIComponent( email )+'?truncateResponse='+truncate+'&includeUnverified='+verified,
                    password:'https://haveibeenpwned.com/api/v2/pwnedpassword/'
                };

                /* Get the first url using "fetch" rather than XMLHttpRequest */
                fetch( urls.username, config ).then( function( res ){
                    if( res.ok ) return res.json();
                    if( res.status==404 )return 404;
                    throw new Error('Failed to check username');                    
                }).then( function( json ){
                    /* Add the response data to output object */
                    data.username=json;
                }).then( function(){
                    /* wait for pre-determined time */
                    return wait( t );
                }).then( function(){
                    /* Get the second url */
                    fetch( urls.email, config ).then(function( res ){
                        if( res.ok ) return res.json();
                        if( res.status==404 )return 404;
                        throw new Error('Failed to check email');
                    }).then( function( json ){
                        /* Add new response data to output object */
                        data.email=json;
                    }).then( function(){
                        /* Loiter, with intent, for a while... twiddle the thumbs etc */
                        return wait( t );
                    }).then( function(){

                        /* Finally get the last url - using POST as I found I was having issues with GET for some reason */
                        var headers=new Headers();
                            headers.append('Content-Type','application/x-www-form-urlencoded; charset=UTF-8')

                        var config={
                            'mode':'cors',
                            'method':'post',
                            'body':'Password='+encodeURIComponent( password ),
                            'headers':headers
                        };

                        fetch( urls.password, config ).then( function( res ){
                            if( res.ok ) return res.json();
                            if( res.status==404 )return 404;
                            throw new Error('Failed to check password');
                        }).then( function(status){
                            /* And store the response */
                            data.password=status==200 ? 'pwned' : 'ok';
                            return status;
                        }).then(function(status){
                            return data;
                        }).then( function( data ){
                            /* play with the data */
                            process.call( this, data );
                        }).catch( evtError );
                    }).catch( evtError );
                }).catch( evtError );
            }



            document.addEventListener('DOMContentLoaded',function(){
                var bttn=document.querySelector('input[type="button"][name="pwnage"]');
                bttn.onclick=pwned;
            },flags);

        </script>
    </head>
    <body>
        <form method='post'>
            <input type='button' name='pwnage' value='Check pwnage' />
            <div id='results'></div>
        </form>
    </body>
</html>

我发现有时可以将超时时间降低到1000毫秒,但似乎有点不稳定。链接方法的实现可能会有所改进,但这是我第一次尝试使用fetch

的复杂用法

进行进一步的测试让我尝试了一些我自己的电子邮件地址,因为我已经有一段时间不在have I been pwned了 - 在找到一对夫妇之后不是一个快乐的兔子:(