我有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);
}
});
}
答案 0 :(得分:3)
首先,这是一个帮助函数,它将返回一个将在15毫秒内解析的Promise。
function delay15 () {
return new Promise(function(resolve) { setTimeout(resolve, 15) })
}
您需要撰写checkusername
,checkemail
和&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了 - 在找到一对夫妇之后不是一个快乐的兔子:( / p>