Comparing version 0.7.0 to 1.0.0
@@ -11,3 +11,5 @@ { | ||
"ajax", | ||
"promises" | ||
"request", | ||
"promise", | ||
"xhr" | ||
], | ||
@@ -19,3 +21,4 @@ "authors": ["Aurélien Delogu"], | ||
}, | ||
"homepage": "http://dreamysource.fr/product/qwest" | ||
"homepage": "http://dreamysource.fr/product/qwest", | ||
"ignore": [".git"] | ||
} |
@@ -22,3 +22,11 @@ module.exports = function(grunt) { | ||
browser : true, | ||
predef : ['Document', 'define', 'module', 'ActiveXObject', 'console', 'log'], | ||
predef : [ | ||
'Document', | ||
'define', | ||
'module', | ||
'ActiveXObject', | ||
'console', | ||
'XDomainRequest', | ||
'log' | ||
], | ||
boss : true, | ||
@@ -54,2 +62,14 @@ curly : true, | ||
} | ||
}, | ||
// Publish on NPM | ||
shell: { | ||
options: { | ||
stderr: false | ||
}, | ||
npm: { | ||
command: 'npm publish' | ||
}, | ||
jam: { | ||
command: 'jam publish' | ||
} | ||
} | ||
@@ -59,10 +79,4 @@ }); | ||
// Define tasks | ||
grunt.registerTask('npm', 'Publish on NPM',function(){ | ||
child_process.exec('npm publish', {cwd: '.'}, function(err,stdout,stderr){ | ||
console.info(stdout); | ||
console.error(stderr); | ||
}); | ||
}); | ||
grunt.registerTask('default', ['clean', 'jshint', 'uglify', 'string-replace', 'npm']); | ||
grunt.registerTask('default', ['clean', 'jshint', 'uglify', 'string-replace', 'shell']); | ||
}; |
{ | ||
"name": "qwest", | ||
"description": "Ajax library with XHR2, promises and requests limitation", | ||
"version": "0.7.0", | ||
"version": "1.0.0", | ||
"author": "Aurélien Delogu <pyrsmk@dreamysource.fr> (http://dreamysource.fr)", | ||
@@ -13,3 +13,5 @@ "repository": { | ||
"ajax", | ||
"promises" | ||
"request", | ||
"promise", | ||
"xhr" | ||
], | ||
@@ -27,2 +29,3 @@ "license": "MIT", | ||
"grunt-contrib-uglify": "~0.4.0", | ||
"grunt-shell": "^1.1.1", | ||
"grunt-string-replace": "^1.0.0", | ||
@@ -29,0 +32,0 @@ "jit-grunt": "^0.9.0" |
@@ -1,1 +0,1 @@ | ||
!function(a){"function"==typeof define?define(a):"undefined"!=typeof module?module.exports=a:this.qwest=a}(function(){var win=window,limit=null,requests=0,request_stack=[],getXHR=function(){return win.XMLHttpRequest?new XMLHttpRequest:new ActiveXObject("Microsoft.XMLHTTP")},version2=""===getXHR().responseType,qwest=function(method,url,data,options,before){data=data||null,options=options||{};var typeSupported=!1,xhr=getXHR(),async=void 0===options.async?!0:!!options.async,cache=options.cache,type=options.type?options.type.toLowerCase():"json",user=options.user||"",password=options.password||"",headers={"X-Requested-With":"XMLHttpRequest"},accepts={xml:"application/xml, text/xml",html:"text/html",json:"application/json, text/javascript",js:"application/javascript, text/javascript"},toUpper=function(a,b,c){return b+c.toUpperCase()},vars="",i,j,parseError="parseError",serialized,success_stack=[],error_stack=[],complete_stack=[],response,success,error,func,promises={success:function(a){return async?success_stack.push(a):success&&a.apply(xhr,[response]),promises},error:function(a){return async?error_stack.push(a):error&&a.apply(xhr,[response]),promises},complete:function(a){return async?complete_stack.push(a):a.apply(xhr),promises}},promises_limit={success:function(a){return request_stack[request_stack.length-1].success.push(a),promises_limit},error:function(a){return request_stack[request_stack.length-1].error.push(a),promises_limit},complete:function(a){return request_stack[request_stack.length-1].complete.push(a),promises_limit}},handleResponse=function(){var i,req,p;if(--requests,request_stack.length){for(req=request_stack.shift(),p=qwest(req.method,req.url,req.data,req.options,req.before),i=0;func=req.success[i];++i)p.success(func);for(i=0;func=req.error[i];++i)p.error(func);for(i=0;func=req.complete[i];++i)p.complete(func)}try{if(!/^2/.test(xhr.status))throw xhr.status+" ("+xhr.statusText+")";var responseText="responseText",responseXML="responseXML";if(typeSupported&&void 0!==xhr.response)response=xhr.response;else switch(type){case"json":try{response=win.JSON?win.JSON.parse(xhr[responseText]):eval("("+xhr[responseText]+")")}catch(e){throw"Error while parsing JSON body"}break;case"js":response=eval(xhr[responseText]);break;case"xml":if(!xhr[responseXML]||xhr[responseXML][parseError]&&xhr[responseXML][parseError].errorCode&&xhr[responseXML][parseError].reason)throw"Error while parsing XML body";response=xhr[responseXML];break;default:response=xhr[responseText]}if(success=!0,async)for(i=0;func=success_stack[i];++i)func.apply(xhr,[response])}catch(e){if(error=!0,response="Request to '"+url+"' aborted: "+e,async)for(i=0;func=error_stack[i];++i)func.apply(xhr,[response])}if(async)for(i=0;func=complete_stack[i];++i)func.apply(xhr)},buildData=function(a,b){var c=[],d=encodeURIComponent;if("object"==typeof a&&null!=a)for(var e in a)a.hasOwnProperty(e)&&(c=c.concat(buildData(a[e],b?b+"["+e+"]":e)));else null!=a&&null!=b&&c.push(d(b)+"="+d(a));return c.join("&")};if(options.headers)for(i in options.headers)headers[i]=options.headers[i];if(limit&&requests==limit)return request_stack.push({method:method,url:url,data:data,options:options,before:before,success:[],error:[],complete:[]}),promises_limit;if(++requests,win.ArrayBuffer&&(data instanceof ArrayBuffer||data instanceof Blob||data instanceof Document||data instanceof FormData)?"GET"==method&&(data=null):/\/json$/.test(headers["Content-Type"])?data=JSON.stringify(data):(data=buildData(data),serialized=!0),"GET"==method&&(vars+=data),null==cache&&(cache="POST"==method),cache||(vars&&(vars+="&"),vars+="__t="+Date.now()),vars&&(url+=(/\?/.test(url)?"&":"?")+vars),xhr.open(method,url,async,user,password),type&&version2)try{xhr.responseType=type,typeSupported=xhr.responseType==type}catch(e){}version2?xhr.onload=handleResponse:xhr.onreadystatechange=function(){4==xhr.readyState&&handleResponse()};for(i in headers)j=i.replace(/(^|-)([^-])/g,toUpper),j!=i&&(headers[j]=headers[i],delete headers[i]),xhr.setRequestHeader(j,headers[j]);return!headers["Content-Type"]&&serialized&&"POST"==method&&xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded"),headers.Accept||xhr.setRequestHeader("Accept",accepts[type]),before&&before.apply(xhr),xhr.send("POST"==method?data:null),promises};return{get:function(a,b,c,d){return qwest("GET",a,b,c,d)},post:function(a,b,c,d){return qwest("POST",a,b,c,d)},xhr2:version2,limit:function(a){limit=a}}}()); | ||
!function(a,b,c){"undefined"!=typeof module&&module.exports?module.exports=c():"function"==typeof define&&define.amd?define(c):a[b]=c()}(this,"qwest",function(){var win=window,doc=document,before,limit=null,requests=0,request_stack=[],getXHR=function(){return win.XMLHttpRequest?new XMLHttpRequest:new ActiveXObject("Microsoft.XMLHTTP")},xhr2=""===getXHR().responseType,qwest=function(method,url,data,options,before){method=method.toUpperCase(),data=data||null,options=options||{};var nativeResponseParsing=!1,crossOrigin,xhr,xdr=!1,timeoutInterval,retries=0,headers={},mimeTypes={text:"*/*",xml:"application/xml",json:"application/json",js:"application/javascript",arraybuffer:null,formdata:null,document:null,file:null,blob:null},contentType="Content-Type",vars="",i,j,serialized,then_stack=[],catch_stack=[],complete_stack=[],response,success,error,func,promises={then:function(a){return options.async?then_stack.push(a):success&&a.call(xhr,response),promises},"catch":function(a){return options.async?catch_stack.push(a):error&&a.call(xhr,response),promises},complete:function(a){return options.async?complete_stack.push(a):a.call(xhr),promises}},promises_limit={then:function(a){return request_stack[request_stack.length-1].then.push(a),promises_limit},"catch":function(a){return request_stack[request_stack.length-1]["catch"].push(a),promises_limit},complete:function(a){return request_stack[request_stack.length-1].complete.push(a),promises_limit}},handleResponse=function(){var i,req,p;if(--requests,request_stack.length){for(req=request_stack.shift(),p=qwest(req.method,req.url,req.data,req.options,req.before),i=0;func=req.then[i];++i)p.then(func);for(i=0;func=req["catch"][i];++i)p["catch"](func);for(i=0;func=req.complete[i];++i)p.complete(func)}try{if(clearInterval(timeoutInterval),!/^2|1223/.test(xhr.status))throw xhr.status+" ("+xhr.statusText+")";var responseText="responseText",responseXML="responseXML",parseError="parseError";if(nativeResponseParsing&&"response"in xhr&&null!==xhr.response)response=xhr.response;else if("document"==options.responseType){var frame=doc.createElement("iframe");frame.style.display="none",doc.body.appendChild(frame),frame.contentDocument.open(),frame.contentDocument.write(xhr.response),frame.contentDocument.close(),response=frame.contentDocument,doc.body.removeChild(frame)}else switch(options.responseType){case"json":try{response="JSON"in win?JSON.parse(xhr[responseText]):eval("("+xhr[responseText]+")")}catch(e){throw"Error while parsing JSON body : "+e}break;case"js":response=eval(xhr[responseText]);break;case"xml":if(!xhr[responseXML]||xhr[responseXML][parseError]&&xhr[responseXML][parseError]["catch"].catchCode&&xhr[responseXML][parseError].reason)throw"Error while parsing XML body";response=xhr[responseXML];break;default:response=xhr[responseText]}if(success=!0,options.async)for(i=0;func=then_stack[i];++i)func.call(xhr,response)}catch(e){if(error=!0,response="Request to '"+url+"' aborted: "+e,options.async)for(i=0;func=catch_stack[i];++i)func.call(xhr,response)}if(options.async)for(i=0;func=complete_stack[i];++i)func.call(xhr)},buildData=function(a,b){var c,d=[],e=encodeURIComponent;if("object"==typeof a&&null!=a)for(c in a)a.hasOwnProperty(c)&&(d=d.concat(buildData(a[c],b?b+"["+c+"]":c)));else null!=a&&null!=b&&d.push(e(b)+"="+e(a));return d.join("&")};switch(++requests,options.async="async"in options?!!options.async:!0,options.cache="cache"in options?!!options.cache:"GET"!=method,options.dataType="dataType"in options?options.dataType.toLowerCase():"post",options.responseType="responseType"in options?options.responseType.toLowerCase():"json",options.user=options.user||"",options.password=options.password||"",options.withCredentials=!!options.withCredentials,options.timeout=options.timeout?parseInt(options.timeout,10):3e3,options.retries=options.retries?parseInt(options.retries,10):3,i=url.match(/\/\/(.+?)\//),crossOrigin=i&&i[1]?i[1]!=location.host:!1,"ArrayBuffer"in win&&data instanceof ArrayBuffer?options.dataType="arraybuffer":"Blob"in win&&data instanceof Blob?options.dataType="blob":"Document"in win&&data instanceof Document?options.dataType="document":"FormData"in win&&data instanceof FormData&&(options.dataType="formdata"),options.dataType){case"json":data=JSON.stringify(data);break;case"post":data=buildData(data)}if(options.headers){var format=function(a,b,c){return b+c.toUpperCase()};for(i in options.headers)headers[i.replace(/(^|-)([^-])/g,format)]=options.headers[i]}if(headers[contentType]||"GET"==method||(options.dataType in mimeTypes?mimeTypes[options.dataType]&&(headers[contentType]=mimeTypes[options.dataType]):headers[contentType]="application/x-www-form-urlencoded"),headers.Accept||(headers.Accept=options.responseType in mimeTypes?mimeTypes[options.responseType]:"*"),crossOrigin||headers["X-Requested-With"]||(headers["X-Requested-With"]="XMLHttpRequest"),"GET"==method&&(vars+=data),options.cache||(vars&&(vars+="&"),vars+="__t="+ +new Date),vars&&(url+=(/\?/.test(url)?"&":"?")+vars),limit&&requests==limit)return request_stack.push({method:method,url:url,data:data,options:options,before:before,then:[],"catch":[],complete:[]}),promises_limit;var send=function(){xhr=getXHR(),crossOrigin&&("withCredentials"in xhr||!win.XDomainRequest||(xhr=new XDomainRequest,xdr=!0,"GET"!=method&&"POST"!=method&&(method="POST"))),xdr?xhr.open(method,url):(xhr.open(method,url,options.async,options.user,options.password),xhr2&&options.async&&(xhr.withCredentials=options.withCredentials));for(var a in headers)xhr.setRequestHeader(a,headers[a]);if(xhr2&&"document"!=options.responseType)try{xhr.responseType=options.responseType,nativeResponseParsing=xhr.responseType==options.responseType}catch(b){}xhr2||xdr?xhr.onload=handleResponse:xhr.onreadystatechange=function(){4==xhr.readyState&&handleResponse()},"overrideMimeType"in xhr&&xhr.overrideMimeType(mimeTypes[options.responseType]),before&&before.call(xhr),xdr?setTimeout(function(){xhr.send()},0):xhr.send("GET"!=method?data:null)},timeout=function(){timeoutInterval=setTimeout(function(){if(xhr.abort(),options.retries&&++retries==options.retries){if(error=!0,response="Request to '"+url+"' aborted: timeout",options.async)for(i=0;func=catch_stack[i];++i)func.call(xhr,response)}else timeout(),send()},options.timeout)};return timeout(),send(),promises},create=function(a){return function(b,c,d){var e=before;return before=null,qwest(a,b,c,d,e)}},obj={before:function(a){return before=a,obj},get:create("GET"),post:create("POST"),put:create("PUT"),"delete":create("DELETE"),xhr2:xhr2,limit:function(a){limit=a}};return obj}); |
226
README.md
@@ -1,5 +0,5 @@ | ||
qwest 0.7.0 | ||
qwest 1.0.0 | ||
=========== | ||
Qwest is a simple ajax library based on `promises` behaviour and that supports `XmlHttpRequest2` special data like `ArrayBuffer`, `Blob`, `Document` and `FormData`. | ||
Qwest is a simple ajax library based on `promises` behaviour and that supports `XmlHttpRequest2` special data like `ArrayBuffer`, `Blob` and `FormData`. | ||
@@ -12,2 +12,3 @@ Install | ||
``` | ||
jam install qwest | ||
bower install qwest | ||
@@ -17,48 +18,85 @@ npm install qwest --save-dev | ||
Syntax | ||
Changes since 0.7 | ||
----------------- | ||
- use `then()` and `catch()` promises instead of `success()` and `error()` | ||
- the `type` option has been replaced by `responseType` | ||
- `dataType` option has been added | ||
- the `before` callback has now its own promise (see it in action at the bottom of the doc) | ||
- added CORS support; `XDomainRequest` for IE8/9 is supported as well | ||
- added timeout/retries support | ||
- handle PUT/DELETE requests | ||
Quick examples | ||
-------------- | ||
```javascript | ||
qwest.get('example.com') | ||
.then(function(response){ | ||
alert(response); | ||
}); | ||
``` | ||
```javascript | ||
qwest.post('example.com',{ | ||
firstname: 'Pedro', | ||
lastname: 'Sanchez', | ||
age: 30 | ||
}) | ||
.then(function(response){ | ||
// Make some useful actions | ||
}) | ||
.catch(function(message){ | ||
// Print the error message | ||
}); | ||
``` | ||
Basics | ||
------ | ||
```javascript | ||
qwest.<method>(<url>,[data],[options],[before]) | ||
.success(function(response){ | ||
// Run when the request is successful | ||
}) | ||
.error(function(message){ | ||
// Process error message | ||
}) | ||
.complete(function(){ | ||
// Always run | ||
}); | ||
qwest.<method>(<url>,[data],[options]) | ||
.then(function(response){ | ||
// Run when the request is successful | ||
}) | ||
.catch(function(message){ | ||
// Process error message | ||
}) | ||
.complete(function(){ | ||
// Always run | ||
}); | ||
``` | ||
The method is either `get` or `post`. There's no `put` or `delete` support because the `XmlHttpRequest` object does not support data sending with those methods. | ||
The method is either `get`, `post`, `put` or `delete`. The `data` parameter can be a multi-dimensional array or object, a string, an ArrayBuffer, a Blob, etc... If you don't want to pass any data but specify some options, set data to `null`. | ||
The `data` parameter is an object that list data to send. It supports multi-dimensional arrays and objects. | ||
The available `options` are : | ||
- type : either [XHR2 supported types](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest#Properties), text, html, json (by default), js or xml; used to have automatic parsing of the response and a valid `Accept` header | ||
- cache : true or false (default is `false` for GET requests and `true` for POST requests); used to disable browser caching using a query parameter `__t` with request timestamp | ||
- dataType : 'post' (by default), 'json', 'text', 'arraybuffer', 'blob', 'document' or 'formdata' (you don't need to specify XHR2 types since they're automatically detected) | ||
- responseType : the response type; either 'json' (by default), 'js', 'xml', 'text', 'arraybuffer', 'blob' or 'document' | ||
- cache : browser caching; default is `false` for GET requests and `true` for POST requests | ||
- async : true (default) or false; used to make asynchronous or synchronous requests | ||
- user : the user to access to the URL, if needed | ||
- password : the password to access to the URL, if needed | ||
- headers: javascript object containing headers to be sent | ||
- headers : javascript object containing headers to be sent | ||
- withCredentials : false by default; sends [credentials](http://www.w3.org/TR/XMLHttpRequest2/#user-credentials) with your XHR2 request ([more info in that post](https://dev.opera.com/articles/xhr2/#xhrcredentials)) | ||
- timeout : the timeout for the request in ms; 3000 by default | ||
- retries : the number of times the request would be runned if the timeout is reached; 3 by default; if you want to remove the limit set it to `null` | ||
The `before` option lets you specify a callback to modify the `XHR` object before the request occurs. | ||
In each callback, the `this` keyword refers to the `XmlHttpRequest` object, so you can do some specific tasks you may need. | ||
You can also verify the XHR object version to handle fallbacks : | ||
```javascript | ||
if(qwest.xhr2){ | ||
// Actions for XHR2 | ||
} | ||
else{ | ||
// Actions for XHR1 | ||
} | ||
qwest.get('example.com') | ||
.then(function(response){ | ||
// Blah blah blah | ||
}) | ||
.catch(function(message){ | ||
log(this.responseText); | ||
throw message; | ||
}); | ||
``` | ||
Requests limitation | ||
------------------- | ||
Request limitation | ||
------------------ | ||
Requests limitation is a very powerful functionnality which avoids browser freezes and server overloads. It's really useful for freeing bandwidth and memory resources when you have a whole bunch of requests to do at the same time (when you load a gallery, per example). You just need to set the request limit and when the count is reached qwest will stock all further requests to start them when a slot is free. | ||
One of the great qwest's functionnalities is the request limitation. It avoids browser freezes and server overloads by freeing bandwidth and memory resources when you have a whole bunch of requests to do at the same time (when you load a gallery, per example). You just need to set the request limit and when the count is reached qwest will stock all further requests and start them when a slot is free. | ||
@@ -68,101 +106,89 @@ ```javascript | ||
$$('.foo').each(function(){ | ||
qwest.get(this.data('some_url_to_get')); | ||
$('.foo').forEach(function(){ | ||
qwest.get(this.data('some_url_to_get')); | ||
}); | ||
``` | ||
If you want to remove the limit, just do `qwest.limit(null)`. | ||
If you want to remove the limit, do `qwest.limit(null)`. | ||
Some examples | ||
------------- | ||
Set options to XHR | ||
------------------ | ||
Send a simple GET request : | ||
If you want to apply some manual options to the `XHR` object, you can use the `before` promise. It must be called before __any__ other promise. The `this` keyword refers to the `XHR` object itself. | ||
```javascript | ||
qwest.get('example.com') | ||
.success(function(response){ | ||
alert(response); | ||
}); | ||
qwest.before(function(){ | ||
this.uploadonprogress=function(e){ | ||
// Upload in progress | ||
}; | ||
}) | ||
.get('example.com') | ||
.then(function(response){ | ||
// Blah blah blah | ||
}); | ||
``` | ||
Send a synchronous POST request with data : | ||
Handling fallbacks | ||
------------------ | ||
XHR2 is not available on every browser, so, if needed, you can simply verify the XHR version. | ||
```javascript | ||
qwest.post('example.com',{foo:'bar'},{async:false}) | ||
.success(function(response){ | ||
// Make some useful actions | ||
}) | ||
.error(function(message){ | ||
log(message); | ||
}); | ||
if(qwest.xhr2){ | ||
// Actions for XHR2 | ||
} | ||
else{ | ||
// Actions for XHR1 | ||
} | ||
``` | ||
As seen, qwest methods are chainable and you can specify multiple `success`, `error` or `complete` callbacks : | ||
Receiving binary data in older browsers | ||
--------------------------------------- | ||
Getting binary data in legacy browsers needs a trick, as we can read it on [MDN](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Sending_and_Receiving_Binary_Data#Receiving_binary_data_in_older_browsers). In qwest, that's how we could handle it : | ||
```javascript | ||
qwest.post('example.com',{foo:'bar'}) | ||
.success(function(response){ | ||
// Make some useful actions | ||
}) | ||
.success(function(response){ | ||
// And other actions | ||
}) | ||
.error(function(message){ | ||
// Log here | ||
}) | ||
.error(function(message){ | ||
// Maybe here | ||
}) | ||
.error(function(message){ | ||
// Or here | ||
}) | ||
.complete(function(message){ | ||
// Finally, execute that | ||
}); | ||
qwest.before(function(){ | ||
this.overrideMimeType('text\/plain; charset=x-user-defined'); | ||
}) | ||
.get('example.com/file') | ||
.then(function(response){ | ||
// response is now a binary string | ||
}); | ||
``` | ||
In each callback, the `this` keyword is the `XmlHttpRequest` object, so you can do some specific tasks you may need. | ||
Compatibility notes | ||
------------------- | ||
According to this [compatibility table](https://kangax.github.io/compat-table/es5), IE7/8 do not support using `catch` and `delete` as method name because these are reserved words. If you want to support those browsers you should write : | ||
```javascript | ||
qwest.get('example.com') | ||
.success(function(response){ | ||
// Blah blah blah | ||
}) | ||
.error(function(message){ | ||
log(this.responseText); | ||
throw message; | ||
}); | ||
qwest.delete('example.com') | ||
.then(function(){}) | ||
.catch(function(){}); | ||
``` | ||
To apply some manual options to the `XHR` object, define a `before` callback : | ||
Like this : | ||
```javascript | ||
qwest.get('example.com',{},{},function(){ | ||
this.uploadonprogress=function(e){ | ||
// Upload in progress | ||
}; | ||
}) | ||
.success(function(response){ | ||
// Blah blah blah | ||
}); | ||
qwest['delete']('example.com') | ||
.then(function(){}) | ||
['catch'](function(){}); | ||
``` | ||
Please note that the default "Content-Type" header is "application/x-www-form-urlencoded". Overwrite it if you want ;) | ||
The CORS object shipped with IE8 and 9 is `XDomainRequest`. This object __does not__ support `PUT` and `DELETE` requests. | ||
Example for posting json data: | ||
```javascript | ||
qwest.post('example.com',{data:"mydata"},{ | ||
headers:{ | ||
"Content-Type":"application/json" | ||
} | ||
}) | ||
.success(function(response){ | ||
// Blah blah blah | ||
}); | ||
``` | ||
XHR2 does not support `arraybuffer`, `blob` and `document` response types in synchroneous mode. | ||
Last notes | ||
---------- | ||
- if an error occurs in a `then()` callback, it will be catched by the `catch()` promise | ||
- the default `Content-Type` header is `application/x-www-form-urlencoded` for `post` and `xhr2` data types, with a `POST` request | ||
- the `js` response type executes a remote javascript file and returns its raw code in the `then()` promise | ||
- if you want to set or get raw data, set the related option to `text` | ||
License | ||
------- | ||
[MIT license](http://dreamysource.mit-license.org) everywhere! | ||
[MIT license](http://dreamysource.mit-license.org) everywhere! |
622
src/qwest.js
@@ -5,19 +5,21 @@ | ||
Author | ||
Aurélien Delogu (dev@dreamysource.fr) | ||
Site | ||
https://github.com/pyrsmk/qwest | ||
*/ | ||
(function(def){ | ||
if(typeof define=='function'){ | ||
define(def); | ||
;(function(context,name,definition){ | ||
if(typeof module!='undefined' && module.exports){ | ||
module.exports=definition(); | ||
} | ||
else if(typeof module!='undefined'){ | ||
module.exports=def; | ||
else if(typeof define=='function' && define.amd){ | ||
define(definition); | ||
} | ||
else{ | ||
this.qwest=def; | ||
context[name]=definition(); | ||
} | ||
}(function(){ | ||
}(this,'qwest',function(){ | ||
var win=window, | ||
doc=document, | ||
before, | ||
// Variables for limit mechanism | ||
@@ -29,8 +31,8 @@ limit=null, | ||
getXHR=function(){ | ||
return win.XMLHttpRequest? | ||
new XMLHttpRequest(): | ||
new ActiveXObject('Microsoft.XMLHTTP'); | ||
return win.XMLHttpRequest? | ||
new XMLHttpRequest(): | ||
new ActiveXObject('Microsoft.XMLHTTP'); | ||
}, | ||
// Guess XHR version | ||
version2=(getXHR().responseType===''), | ||
xhr2=(getXHR().responseType===''), | ||
@@ -41,27 +43,31 @@ // Core function | ||
// Format | ||
method=method.toUpperCase(); | ||
data=data || null; | ||
options=options || {}; | ||
var typeSupported=false, | ||
xhr=getXHR(), | ||
async=options.async===undefined?true:!!options.async, | ||
cache=options.cache, | ||
type=options.type?options.type.toLowerCase():'json', | ||
user=options.user || '', | ||
password=options.password || '', | ||
headers={'X-Requested-With':'XMLHttpRequest'}, | ||
accepts={ | ||
xml : 'application/xml, text/xml', | ||
html: 'text/html', | ||
//text: 'text/plain', | ||
json: 'application/json, text/javascript', | ||
js : 'application/javascript, text/javascript' | ||
// Define variables | ||
var nativeResponseParsing=false, | ||
crossOrigin, | ||
xhr, | ||
xdr=false, | ||
timeoutInterval, | ||
retries=0, | ||
headers={}, | ||
mimeTypes={ | ||
text: '*/*', | ||
xml: 'application/xml', | ||
json: 'application/json', | ||
js: 'application/javascript', | ||
arraybuffer: null, | ||
formdata: null, | ||
document: null, | ||
file: null, | ||
blob: null | ||
}, | ||
toUpper=function(match,p1,p2){return p1+p2.toUpperCase();}, | ||
contentType='Content-Type', | ||
vars='', | ||
i,j, | ||
parseError='parseError', | ||
serialized, | ||
success_stack=[], | ||
error_stack=[], | ||
then_stack=[], | ||
catch_stack=[], | ||
complete_stack=[], | ||
@@ -72,196 +78,232 @@ response, | ||
func, | ||
// Define promises | ||
promises={ | ||
success:function(func){ | ||
if(async){ | ||
success_stack.push(func); | ||
} | ||
else if(success){ | ||
func.apply(xhr,[response]); | ||
} | ||
return promises; | ||
}, | ||
error:function(func){ | ||
if(async){ | ||
error_stack.push(func); | ||
} | ||
else if(error){ | ||
func.apply(xhr,[response]); | ||
} | ||
return promises; | ||
}, | ||
complete:function(func){ | ||
if(async){ | ||
complete_stack.push(func); | ||
} | ||
else{ | ||
func.apply(xhr); | ||
} | ||
return promises; | ||
// Define promises | ||
promises={ | ||
then:function(func){ | ||
if(options.async){ | ||
then_stack.push(func); | ||
} | ||
else if(success){ | ||
func.call(xhr,response); | ||
} | ||
return promises; | ||
}, | ||
promises_limit={ | ||
success:function(func){ | ||
request_stack[request_stack.length-1].success.push(func); | ||
return promises_limit; | ||
}, | ||
error:function(func){ | ||
request_stack[request_stack.length-1].error.push(func); | ||
return promises_limit; | ||
}, | ||
complete:function(func){ | ||
request_stack[request_stack.length-1].complete.push(func); | ||
return promises_limit; | ||
'catch':function(func){ | ||
if(options.async){ | ||
catch_stack.push(func); | ||
} | ||
else if(error){ | ||
func.call(xhr,response); | ||
} | ||
return promises; | ||
}, | ||
// Handle the response | ||
handleResponse=function(){ | ||
// Prepare | ||
var i,req,p; | ||
--requests; | ||
// Launch next stacked request | ||
if(request_stack.length){ | ||
req=request_stack.shift(); | ||
p=qwest(req.method,req.url,req.data,req.options,req.before); | ||
for(i=0;func=req.success[i];++i){ | ||
p.success(func); | ||
} | ||
for(i=0;func=req.error[i];++i){ | ||
p.error(func); | ||
} | ||
for(i=0;func=req.complete[i];++i){ | ||
p.complete(func); | ||
} | ||
complete:function(func){ | ||
if(options.async){ | ||
complete_stack.push(func); | ||
} | ||
// Handle response | ||
try{ | ||
// Verify status code | ||
if(!/^2/.test(xhr.status)){ | ||
throw xhr.status+' ('+xhr.statusText+')'; | ||
} | ||
// Init | ||
var responseText='responseText', | ||
responseXML='responseXML'; | ||
// Process response | ||
/*if(type=='text' || type=='html'){ | ||
response=xhr[responseText]; | ||
} | ||
else */if(typeSupported && xhr.response!==undefined){ | ||
response=xhr.response; | ||
} | ||
else{ | ||
switch(type){ | ||
case 'json': | ||
try{ | ||
if(win.JSON){ | ||
response=win.JSON.parse(xhr[responseText]); | ||
} | ||
else{ | ||
response=eval('('+xhr[responseText]+')'); | ||
} | ||
else{ | ||
func.call(xhr); | ||
} | ||
return promises; | ||
} | ||
}, | ||
promises_limit={ | ||
then:function(func){ | ||
request_stack[request_stack.length-1].then.push(func); | ||
return promises_limit; | ||
}, | ||
'catch':function(func){ | ||
request_stack[request_stack.length-1]['catch'].push(func); | ||
return promises_limit; | ||
}, | ||
complete:function(func){ | ||
request_stack[request_stack.length-1].complete.push(func); | ||
return promises_limit; | ||
} | ||
}, | ||
// Handle the response | ||
handleResponse=function(){ | ||
// Prepare | ||
var i,req,p; | ||
--requests; | ||
// Launch next stacked request | ||
if(request_stack.length){ | ||
req=request_stack.shift(); | ||
p=qwest(req.method,req.url,req.data,req.options,req.before); | ||
for(i=0;func=req.then[i];++i){ | ||
p.then(func); | ||
} | ||
for(i=0;func=req['catch'][i];++i){ | ||
p['catch'](func); | ||
} | ||
for(i=0;func=req.complete[i];++i){ | ||
p.complete(func); | ||
} | ||
} | ||
// Handle response | ||
try{ | ||
// Clear the timeout | ||
clearInterval(timeoutInterval); | ||
// Verify status code | ||
if(!/^2|1223/.test(xhr.status)){ // https://stackoverflow.com/questions/10046972/msie-returns-status-code-of-1223-for-ajax-request | ||
throw xhr.status+' ('+xhr.statusText+')'; | ||
} | ||
// Init | ||
var responseText='responseText', | ||
responseXML='responseXML', | ||
parseError='parseError'; | ||
// Process response | ||
if(nativeResponseParsing && 'response' in xhr && xhr.response!==null){ | ||
response=xhr.response; | ||
} | ||
else if(options.responseType=='document'){ | ||
var frame=doc.createElement('iframe'); | ||
frame.style.display='none'; | ||
doc.body.appendChild(frame); | ||
frame.contentDocument.open(); | ||
frame.contentDocument.write(xhr.response); | ||
frame.contentDocument.close(); | ||
response=frame.contentDocument; | ||
doc.body.removeChild(frame); | ||
} | ||
else{ | ||
switch(options.responseType){ | ||
case 'json': | ||
try{ | ||
if('JSON' in win){ | ||
response=JSON.parse(xhr[responseText]); | ||
} | ||
catch(e){ | ||
throw "Error while parsing JSON body"; | ||
} | ||
break; | ||
case 'js': | ||
response=eval(xhr[responseText]); | ||
break; | ||
case 'xml': | ||
if(!xhr[responseXML] || (xhr[responseXML][parseError] && xhr[responseXML][parseError].errorCode && xhr[responseXML][parseError].reason)){ | ||
throw "Error while parsing XML body"; | ||
} | ||
else{ | ||
response=xhr[responseXML]; | ||
response=eval('('+xhr[responseText]+')'); | ||
} | ||
break; | ||
default: | ||
//throw "Unsupported "+type+" type"; | ||
response=xhr[responseText]; | ||
} | ||
} | ||
catch(e){ | ||
throw "Error while parsing JSON body : "+e; | ||
} | ||
break; | ||
case 'js': | ||
response=eval(xhr[responseText]); | ||
break; | ||
case 'xml': | ||
if(!xhr[responseXML] || (xhr[responseXML][parseError] && xhr[responseXML][parseError]['catch'].catchCode && xhr[responseXML][parseError].reason)){ | ||
throw "Error while parsing XML body"; | ||
} | ||
else{ | ||
response=xhr[responseXML]; | ||
} | ||
break; | ||
default: | ||
response=xhr[responseText]; | ||
} | ||
// Execute success stack | ||
success=true; | ||
if(async){ | ||
for(i=0;func=success_stack[i];++i){ | ||
func.apply(xhr,[response]); | ||
} | ||
} | ||
} | ||
catch(e){ | ||
error=true; | ||
response="Request to '"+url+"' aborted: "+e; | ||
// Execute error stack | ||
if(async){ | ||
for(i=0;func=error_stack[i];++i){ | ||
func.apply(xhr,[response]); | ||
} | ||
// Execute 'then' stack | ||
success=true; | ||
if(options.async){ | ||
for(i=0;func=then_stack[i];++i){ | ||
func.call(xhr,response); | ||
} | ||
} | ||
// Execute complete stack | ||
if(async){ | ||
for(i=0;func=complete_stack[i];++i){ | ||
func.apply(xhr); | ||
} | ||
catch(e){ | ||
error=true; | ||
response="Request to '"+url+"' aborted: "+e; | ||
// Execute 'catch' stack | ||
if(options.async){ | ||
for(i=0;func=catch_stack[i];++i){ | ||
func.call(xhr,response); | ||
} | ||
} | ||
}, | ||
// Recursively build the query string | ||
buildData = function(data, key) { | ||
var res = [], | ||
enc = encodeURIComponent; | ||
if(typeof data === 'object' && data != null) { | ||
for(var p in data) { | ||
if(data.hasOwnProperty(p)) { | ||
res = res.concat(buildData(data[p], key ? key + '[' + p + ']' : p)); | ||
} | ||
} | ||
// Execute complete stack | ||
if(options.async){ | ||
for(i=0;func=complete_stack[i];++i){ | ||
func.call(xhr); | ||
} | ||
} | ||
}, | ||
// Recursively build the query string | ||
buildData=function(data,key){ | ||
var res=[], | ||
enc=encodeURIComponent, | ||
p; | ||
if(typeof data==='object' && data!=null) { | ||
for(p in data) { | ||
if(data.hasOwnProperty(p)) { | ||
res=res.concat(buildData(data[p],key?key+'['+p+']':p)); | ||
} | ||
} else if(data != null && key != null) { | ||
res.push(enc(key) + '=' + enc(data)); | ||
} | ||
return res.join('&'); | ||
}; | ||
//Copy options headers to headers | ||
if(options.headers){ | ||
for(i in options.headers){ | ||
headers[i] = options.headers[i]; | ||
} | ||
} | ||
// Limit requests | ||
if(limit && requests==limit){ | ||
// Stock current request | ||
request_stack.push({ | ||
method : method, | ||
url : url, | ||
data : data, | ||
options : options, | ||
before : before, | ||
success : [], | ||
error : [], | ||
complete : [] | ||
}); | ||
// Return promises | ||
return promises_limit; | ||
} | ||
} | ||
else if(data!=null && key!=null){ | ||
res.push(enc(key)+'='+enc(data)); | ||
} | ||
return res.join('&'); | ||
}; | ||
// New request | ||
++requests; | ||
// Normalize options | ||
options.async='async' in options?!!options.async:true; | ||
options.cache='cache' in options?!!options.cache:(method!='GET'); | ||
options.dataType='dataType' in options?options.dataType.toLowerCase():'post'; | ||
options.responseType='responseType' in options?options.responseType.toLowerCase():'json'; | ||
options.user=options.user || ''; | ||
options.password=options.password || ''; | ||
options.withCredentials=!!options.withCredentials; | ||
options.timeout=options.timeout?parseInt(options.timeout,10):3000; | ||
options.retries=options.retries?parseInt(options.retries,10):3; | ||
// Guess if we're dealing with a cross-origin request | ||
i=url.match(/\/\/(.+?)\//); | ||
crossOrigin=i && i[1]?i[1]!=location.host:false; | ||
// Prepare data | ||
if( | ||
win.ArrayBuffer && | ||
(data instanceof ArrayBuffer || | ||
data instanceof Blob || | ||
data instanceof Document || | ||
data instanceof FormData) | ||
){ | ||
if(method=='GET'){ | ||
data=null; | ||
if('ArrayBuffer' in win && data instanceof ArrayBuffer){ | ||
options.dataType='arraybuffer'; | ||
} | ||
else if('Blob' in win && data instanceof Blob){ | ||
options.dataType='blob'; | ||
} | ||
else if('Document' in win && data instanceof Document){ | ||
options.dataType='document'; | ||
} | ||
else if('FormData' in win && data instanceof FormData){ | ||
options.dataType='formdata'; | ||
} | ||
switch(options.dataType){ | ||
case 'json': | ||
data=JSON.stringify(data); | ||
break; | ||
case 'post': | ||
data=buildData(data); | ||
} | ||
// Prepare headers | ||
if(options.headers){ | ||
var format=function(match,p1,p2){ | ||
return p1+p2.toUpperCase(); | ||
}; | ||
for(i in options.headers){ | ||
headers[i.replace(/(^|-)([^-])/g,format)]=options.headers[i]; | ||
} | ||
} | ||
else if(/\/json$/.test(headers['Content-Type'])){ | ||
data=JSON.stringify(data); | ||
if(!headers[contentType] && method!='GET'){ | ||
if(options.dataType in mimeTypes){ | ||
if(mimeTypes[options.dataType]){ | ||
headers[contentType]=mimeTypes[options.dataType]; | ||
} | ||
} | ||
else{ | ||
headers[contentType]='application/x-www-form-urlencoded'; | ||
} | ||
} | ||
else{ | ||
data = buildData(data); | ||
serialized=true; | ||
if(!headers.Accept){ | ||
headers.Accept=(options.responseType in mimeTypes)?mimeTypes[options.responseType]:'*'; | ||
} | ||
if(!crossOrigin && !headers['X-Requested-With']){ // because that header breaks in legacy browsers with CORS | ||
headers['X-Requested-With']='XMLHttpRequest'; | ||
} | ||
// Prepare URL | ||
@@ -271,10 +313,7 @@ if(method=='GET'){ | ||
} | ||
if(cache==null){ | ||
cache=(method=='POST'); | ||
} | ||
if(!cache){ | ||
if(!options.cache){ | ||
if(vars){ | ||
vars+='&'; | ||
} | ||
vars+='__t='+Date.now(); | ||
vars+='__t='+(+new Date()); | ||
} | ||
@@ -284,44 +323,107 @@ if(vars){ | ||
} | ||
// Open connection | ||
xhr.open(method,url,async,user,password); | ||
// Identify supported XHR version | ||
if(type && version2){ | ||
try{ | ||
xhr.responseType=type; | ||
typeSupported=(xhr.responseType==type); | ||
} | ||
catch(e){} | ||
// The limit has been reached, stock the request | ||
if(limit && requests==limit){ | ||
request_stack.push({ | ||
method : method, | ||
url : url, | ||
data : data, | ||
options : options, | ||
before : before, | ||
then : [], | ||
'catch' : [], | ||
complete: [] | ||
}); | ||
return promises_limit; | ||
} | ||
// Plug response handler | ||
if(version2){ | ||
xhr.onload=handleResponse; | ||
} | ||
else{ | ||
xhr.onreadystatechange=function(){ | ||
if(xhr.readyState==4){ | ||
handleResponse(); | ||
// Send the request | ||
var send=function(){ | ||
// Get XHR object | ||
xhr=getXHR(); | ||
if(crossOrigin){ | ||
if(!('withCredentials' in xhr) && win.XDomainRequest){ | ||
xhr=new XDomainRequest(); // CORS with IE8/9 | ||
xdr=true; | ||
if(method!='GET' && method!='POST'){ | ||
method='POST'; | ||
} | ||
} | ||
}; | ||
} | ||
// Prepare headers | ||
for(i in headers){ | ||
j=i.replace(/(^|-)([^-])/g,toUpper); | ||
if(j != i){ | ||
headers[j]=headers[i]; | ||
delete headers[i]; | ||
} | ||
xhr.setRequestHeader(j,headers[j]); | ||
} | ||
if(!headers['Content-Type'] && serialized && method=='POST'){ | ||
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded'); | ||
} | ||
if(!headers.Accept){ | ||
xhr.setRequestHeader('Accept',accepts[type]); | ||
} | ||
// Before | ||
if(before){ | ||
before.apply(xhr); | ||
} | ||
// Send request | ||
xhr.send(method=='POST'?data:null); | ||
// Open connection | ||
if(xdr){ | ||
xhr.open(method,url); | ||
} | ||
else{ | ||
xhr.open(method,url,options.async,options.user,options.password); | ||
if(xhr2 && options.async){ | ||
xhr.withCredentials=options.withCredentials; | ||
} | ||
} | ||
// Set headers | ||
for(var i in headers){ | ||
xhr.setRequestHeader(i,headers[i]); | ||
} | ||
// Verify if the response type is supported by the current browser | ||
if(xhr2 && options.responseType!='document'){ // Don't verify for 'document' since we're using an internal routine | ||
try{ | ||
xhr.responseType=options.responseType; | ||
nativeResponseParsing=(xhr.responseType==options.responseType); | ||
} | ||
catch(e){} | ||
} | ||
// Plug response handler | ||
if(xhr2 || xdr){ | ||
xhr.onload=handleResponse; | ||
} | ||
else{ | ||
xhr.onreadystatechange=function(){ | ||
if(xhr.readyState==4){ | ||
handleResponse(); | ||
} | ||
}; | ||
} | ||
// Override mime type to ensure the response is well parsed | ||
if('overrideMimeType' in xhr){ | ||
xhr.overrideMimeType(mimeTypes[options.responseType]); | ||
} | ||
// Run 'before' callback | ||
if(before){ | ||
before.call(xhr); | ||
} | ||
// Send request | ||
if(xdr){ | ||
setTimeout(function(){ // https://developer.mozilla.org/en-US/docs/Web/API/XDomainRequest | ||
xhr.send(); | ||
},0); | ||
} | ||
else{ | ||
xhr.send(method!='GET'?data:null); | ||
} | ||
}; | ||
// Timeout/retries | ||
var timeout=function(){ | ||
timeoutInterval=setTimeout(function(){ | ||
xhr.abort(); | ||
if(!options.retries || ++retries!=options.retries){ | ||
timeout(); | ||
send(); | ||
} | ||
else{ | ||
error=true; | ||
response="Request to '"+url+"' aborted: timeout"; | ||
if(options.async){ | ||
for(i=0;func=catch_stack[i];++i){ | ||
func.call(xhr,response); | ||
} | ||
} | ||
} | ||
},options.timeout); | ||
}; | ||
// Start the request | ||
timeout(); | ||
send(); | ||
// Return promises | ||
@@ -332,16 +434,26 @@ return promises; | ||
// Return final qwest object | ||
return { | ||
get:function(url,data,options,before){ | ||
return qwest('GET',url,data,options,before); | ||
// Return external qwest object | ||
var create=function(method){ | ||
return function(url,data,options){ | ||
var b=before; | ||
before=null; | ||
return qwest(method,url,data,options,b); | ||
}; | ||
}, | ||
post:function(url,data,options,before){ | ||
return qwest('POST',url,data,options,before); | ||
obj={ | ||
before: function(callback){ | ||
before=callback; | ||
return obj; | ||
}, | ||
xhr2:version2, | ||
limit:function(by){ | ||
get: create('GET'), | ||
post: create('POST'), | ||
put: create('PUT'), | ||
'delete': create('DELETE'), | ||
xhr2: xhr2, | ||
limit: function(by){ | ||
limit=by; | ||
} | ||
}; | ||
return obj; | ||
}())); | ||
})); |
domready(function(){ | ||
asyncTest('Events',function(){ | ||
if(!String.prototype.trim){ | ||
String.prototype.trim=function(){ | ||
return this.replace(/^\s+|\s+$/g,''); | ||
}; | ||
} | ||
var methods=['get','post','put','delete'], | ||
i,j; | ||
test('XHR2',function(){ | ||
expect(1); | ||
ok(Modernizr.xhr2==qwest.xhr2); | ||
}); | ||
asyncTest('Asynchroneous REST requests',function(){ | ||
expect(4); | ||
var executed=0; | ||
for(i=0,j=methods.length;i<j;++i){ | ||
qwest[methods[i]]('tests/async/test.php?method='+methods[i].toUpperCase()) | ||
.then(function(method){ | ||
return function(response){ | ||
//console.log(response.debug); | ||
ok(response.status=='ok',method+' request'); | ||
if(++executed==4){ | ||
start(); | ||
} | ||
}; | ||
}(methods[i].toUpperCase())) | ||
.catch(function(message){ | ||
ok(false,message); | ||
if(++executed==4){ | ||
start(); | ||
} | ||
}); | ||
} | ||
}); | ||
test('Synchroneous REST requests',function(){ | ||
expect(4); | ||
for(i=0,j=methods.length;i<j;++i){ | ||
qwest[methods[i]]('tests/sync/test.php?method='+methods[i].toUpperCase(),null,{async:false}) | ||
.then(function(response){ | ||
//console.log(response.debug); | ||
ok(response.status=='ok',methods[i].toUpperCase()+' request'); | ||
}) | ||
.catch(function(message){ | ||
ok(false,message); | ||
}); | ||
} | ||
}); | ||
asyncTest('Multiple promises (async)',function(){ | ||
expect(2); | ||
alert("Please trigger responsive events (resize window, zoom-in, zoom-out, text resize"); | ||
var first, | ||
second; | ||
W(function(){ | ||
if(!first){ | ||
first=true; | ||
ok(true,'Event catched by first listener'); | ||
} | ||
}); | ||
W(function(){ | ||
if(!second){ | ||
second=true; | ||
ok(true,'Event catched by second listener'); | ||
var a=0,b=0,c=0; | ||
qwest.get('tests/multiple/test.php') | ||
.then(function(response){ | ||
++a; | ||
}) | ||
.catch(function(message){ | ||
++b; | ||
}) | ||
.then(function(response){ | ||
++a; | ||
}) | ||
.complete(function(){ | ||
++c; | ||
}) | ||
.complete(function(){ | ||
++c; | ||
ok(a==3 && b==0 && c==2,a+'/'+b+'/'+c); | ||
a=0; | ||
b=0; | ||
c=0; | ||
qwest.get('tests/multiple/test2.php') | ||
.then(function(response){ | ||
++a; | ||
}) | ||
.catch(function(message){ | ||
++b; | ||
}) | ||
.then(function(response){ | ||
++a; | ||
}) | ||
.complete(function(){ | ||
++c; | ||
}) | ||
.complete(function(){ | ||
++c; | ||
ok(a==0 && b==2 && c==2,a+'/'+b+'/'+c); | ||
start(); | ||
}) | ||
.then(function(response){ | ||
++a; | ||
}) | ||
.catch(function(message){ | ||
++b; | ||
}); | ||
}) | ||
.then(function(response){ | ||
++a; | ||
}) | ||
.catch(function(message){ | ||
++b; | ||
}); | ||
}); | ||
test('Multiple promises (sync)',function(){ | ||
expect(2); | ||
var a=0,b=0,c=0; | ||
qwest.get('tests/multiple/test.php',null,{async:false}) | ||
.then(function(response){ | ||
++a; | ||
}) | ||
.catch(function(message){ | ||
++b; | ||
}) | ||
.then(function(response){ | ||
++a; | ||
}) | ||
.complete(function(){ | ||
++c; | ||
}) | ||
.complete(function(){ | ||
++c; | ||
}) | ||
.then(function(response){ | ||
++a; | ||
}) | ||
.catch(function(message){ | ||
++b; | ||
}); | ||
ok(a==3 && b==0 && c==2,a+'/'+b+'/'+c); | ||
a=0; | ||
b=0; | ||
c=0; | ||
qwest.get('tests/multiple/test2.php',null,{async:false}) | ||
.then(function(response){ | ||
++a; | ||
}) | ||
.catch(function(message){ | ||
++b; | ||
}) | ||
.then(function(response){ | ||
++a; | ||
}) | ||
.complete(function(){ | ||
++c; | ||
}) | ||
.complete(function(){ | ||
++c; | ||
}) | ||
.then(function(response){ | ||
++a; | ||
}) | ||
.catch(function(message){ | ||
++b; | ||
}); | ||
ok(a==0 && b==2 && c==2,a+'/'+b+'/'+c); | ||
}); | ||
asyncTest('Request limitation (async)',function(){ | ||
expect(20); | ||
qwest.limit(20); | ||
var executed=0; | ||
for(i=1,j=20;i<=j;++i){ | ||
qwest.get('tests/limit/test.php') | ||
.then(function(response){ | ||
ok(response.status=='ok'); | ||
if(++executed==20){ | ||
start(); | ||
} | ||
}) | ||
.catch(function(message){ | ||
ok(false,message); | ||
if(++executed==20){ | ||
start(); | ||
} | ||
}); | ||
} | ||
qwest.limit(null); | ||
}); | ||
test('Request limitation (sync)',function(){ | ||
expect(20); | ||
qwest.limit(20); | ||
for(i=1,j=20;i<=j;++i){ | ||
qwest.get('tests/limit/test.php',null,{async:false}) | ||
.then(function(response){ | ||
ok(response.status=='ok'); | ||
}) | ||
.catch(function(message){ | ||
ok(false,message); | ||
}); | ||
} | ||
qwest.limit(null); | ||
}); | ||
asyncTest('Timeout (async)',function(){ | ||
expect(1); | ||
var t=+new Date; | ||
qwest.get('tests/timeout/test.php',null,{ | ||
timeout: 250, | ||
retries: 4 | ||
}) | ||
.then(function(response){ | ||
ok(false,'the 4x250ms timeout has been reached too early ['+(+new Date-t)+'ms]'); | ||
start(); | ||
} | ||
}); | ||
}) | ||
.catch(function(message){ | ||
ok((+new Date-t)>=1000,'asynchroneous request ['+(+new Date-t)+'ms]'); | ||
start(); | ||
}); | ||
}); | ||
test('Provided width',function(){ | ||
test('Timeout (sync)',function(){ | ||
expect(1); | ||
ok(W(1024)==64,'Format px width in ems [not optimized to pass with text size changing]'); | ||
var t=+new Date; | ||
qwest.get('tests/timeout/test.php',null,{ | ||
timeout: 500, | ||
retries: 4, | ||
async: false | ||
}) | ||
.then(function(response){ | ||
ok(response.status=='ok','synchroneous request ['+(+new Date-t)+'ms]'); | ||
}) | ||
.catch(function(message){ | ||
ok(false,'synchroneous request : '+message); | ||
}); | ||
}); | ||
test('Window width',function(){ | ||
asyncTest('CORS',function(){ | ||
expect(1); | ||
alert("Is "+W()+" it the right current width?"); | ||
ok(W(true)==W(W()),'Get current window width in ems'); | ||
qwest.get('https://maps.googleapis.com/maps/api/geocode/json') | ||
.then(function(response){ | ||
ok(response.status=='ZERO_RESULTS'); | ||
start(); | ||
}) | ||
.catch(function(message){ | ||
ok(false,message); | ||
start(); | ||
}); | ||
}); | ||
asyncTest('Before promise',function(){ | ||
expect(1); | ||
qwest.before(function(){ | ||
this.setRequestHeader('X-Running-Test','before'); | ||
}) | ||
.get('tests/before/test.php') | ||
.then(function(response){ | ||
//console.log(response.debug); | ||
ok(response.status=='ok'); | ||
start(); | ||
}) | ||
.catch(function(message){ | ||
ok(false,message); | ||
start(); | ||
}); | ||
}); | ||
asyncTest('Cache',function(){ | ||
expect(2); | ||
var a,b, | ||
phase2=function(){ | ||
qwest.post('tests/cache/test.php',null,{responseType:'text'}) | ||
.then(function(response){ | ||
//console.log(response); | ||
b=response; | ||
qwest.post('tests/cache/test.php',null,{responseType: 'text'}) | ||
.then(function(response){ | ||
//console.log(response); | ||
ok(response==b,'POST request'); | ||
start(); | ||
}) | ||
.catch(function(message){ | ||
ok(false,message); | ||
start(); | ||
}); | ||
}) | ||
.catch(function(message){ | ||
ok(false,message); | ||
start(); | ||
}); | ||
}; | ||
qwest.get('tests/cache/test.php',null,{responseType:'text'}) | ||
.then(function(response){ | ||
//console.log(response); | ||
a=response; | ||
qwest.get('tests/cache/test.php',null,{responseType:'text'}) | ||
.then(function(response){ | ||
//console.log(response); | ||
ok(response!=a,'GET request'); | ||
phase2(); | ||
}) | ||
.catch(function(message){ | ||
ok(false,message); | ||
phase2(); | ||
}); | ||
}) | ||
.catch(function(message){ | ||
ok(false,message); | ||
phase2(); | ||
}); | ||
}); | ||
asyncTest('Authentication',function(){ | ||
expect(1); | ||
qwest.get('tests/auth/test.php',null,{ | ||
user: 'pyrsmk', | ||
password: 'test' | ||
}) | ||
.then(function(response){ | ||
//console.log(response.debug); | ||
ok(response.status=='ok'); | ||
start(); | ||
}) | ||
.catch(function(message){ | ||
ok(false,message); | ||
start(); | ||
}); | ||
}); | ||
asyncTest('Get JSON response',function(){ | ||
expect(1); | ||
qwest.get('tests/get_json/test.php',null,{responseType:'json'}) | ||
.then(function(response){ | ||
//console.log(response.debug); | ||
ok(response.status=='ok'); | ||
start(); | ||
}) | ||
.catch(function(message){ | ||
ok(false,message); | ||
start(); | ||
}); | ||
}); | ||
asyncTest('Get DOMString response',function(){ | ||
expect(1); | ||
qwest.get('tests/get_text/test.php',null,{responseType:'text'}) | ||
.then(function(response){ | ||
//console.log(response); | ||
ok(response=='ok'); | ||
start(); | ||
}) | ||
.catch(function(message){ | ||
ok(false,message); | ||
start(); | ||
}); | ||
}); | ||
asyncTest('Get XML response',function(){ | ||
expect(1); | ||
qwest.get('tests/get_xml/test.php',null,{responseType:'xml'}) | ||
.then(function(response){ | ||
//console.log(response.getElementsByTagName('status')[0]); | ||
ok(response.getElementsByTagName('status')[0].textContent=='ok'); | ||
start(); | ||
}) | ||
.catch(function(message){ | ||
ok(false,message); | ||
start(); | ||
}); | ||
}); | ||
asyncTest('Get JS response',function(){ | ||
expect(1); | ||
qwest.get('tests/get_js/test.php',null,{responseType:'js'}) | ||
.then(function(response){ | ||
//console.log(response); | ||
ok(window.xmlTest); | ||
start(); | ||
}) | ||
.catch(function(message){ | ||
ok(false,message); | ||
start(); | ||
}); | ||
}); | ||
asyncTest('Get ArrayBuffer response',function(){ | ||
expect(1); | ||
qwest.get('tests/get_arraybuffer/test.php',null,{responseType:'arraybuffer'}) | ||
.then(function(response){ | ||
var arrayBuffer=new Uint8Array(response), | ||
length=arrayBuffer.length; | ||
//console.log(arrayBuffer[0].toString(16)); | ||
//console.log(arrayBuffer[1].toString(16)); | ||
//console.log(arrayBuffer[length-2].toString(16)); | ||
//console.log(arrayBuffer[length-1].toString(16)); | ||
ok( | ||
arrayBuffer[0].toString(16)=='ff' && | ||
arrayBuffer[1].toString(16)=='d8' && | ||
arrayBuffer[length-2].toString(16)=='ff' && | ||
arrayBuffer[length-1].toString(16)=='d9' | ||
); | ||
start(); | ||
}) | ||
.catch(function(message){ | ||
ok(false,message); | ||
start(); | ||
}); | ||
}); | ||
asyncTest('Get Blob response',function(){ | ||
expect(1); | ||
qwest.get('tests/get_blob/test.php',null,{responseType:'blob'}) | ||
.then(function(response){ | ||
//console.log(response); | ||
ok(response.size); | ||
start(); | ||
}) | ||
.catch(function(message){ | ||
ok(false,message); | ||
start(); | ||
}); | ||
}); | ||
asyncTest('Get Document response',function(){ | ||
expect(1); | ||
qwest.get('tests/get_document/test.php',null,{responseType:'document'}) | ||
.then(function(response){ | ||
//console.log(response); | ||
ok(response.querySelector('p').innerText=='ok'); | ||
start(); | ||
}) | ||
.catch(function(message){ | ||
ok(false,message); | ||
start(); | ||
}); | ||
}); | ||
asyncTest('Send basic POST data',function(){ | ||
expect(1); | ||
qwest.post('tests/send_post/test.php',{ | ||
foo: 'bar', | ||
bar: [{foo:'bar'}] | ||
}) | ||
.then(function(response){ | ||
//console.log(response.debug); | ||
ok(response.status.trim()=='ok'); | ||
start(); | ||
}) | ||
.catch(function(message){ | ||
ok(false,message); | ||
start(); | ||
}); | ||
}); | ||
asyncTest('Send JSON data',function(){ | ||
expect(1); | ||
qwest.post('tests/send_json/test.php',{ | ||
foo: 'bar', | ||
bar: [{foo:'bar'}] | ||
},{ | ||
dataType: 'json' | ||
}) | ||
.then(function(response){ | ||
//console.log(response.debug); | ||
ok(response.status=='ok'); | ||
start(); | ||
}) | ||
.catch(function(message){ | ||
ok(false,message); | ||
start(); | ||
}); | ||
}); | ||
asyncTest('Send DOMString data',function(){ | ||
expect(1); | ||
qwest.post('tests/send_text/test.php','text',{dataType:'text'}) | ||
.then(function(response){ | ||
//console.log(response.debug); | ||
ok(response.status=='ok'); | ||
start(); | ||
}) | ||
.catch(function(message){ | ||
ok(false,message); | ||
start(); | ||
}); | ||
}); | ||
asyncTest('Send FormData data',function(){ | ||
expect(1); | ||
var formData=new FormData(); | ||
formData.append('firstname','Pedro'); | ||
formData.append('lastname','Sanchez'); | ||
qwest.post('tests/send_formdata/test.php',formData) | ||
.then(function(response){ | ||
//console.log(response.debug); | ||
ok(response.status=='ok'); | ||
start(); | ||
}) | ||
.catch(function(message){ | ||
ok(false,message); | ||
start(); | ||
}); | ||
}); | ||
asyncTest('Send Blob data',function(){ | ||
expect(1); | ||
var blob=new Blob(['test'],{type:'text/plain'}); | ||
qwest.post('tests/send_blob/test.php',blob) | ||
.then(function(response){ | ||
//console.log(response.debug); | ||
ok(response.status=='ok'); | ||
start(); | ||
}) | ||
.catch(function(message){ | ||
ok(false,message); | ||
start(); | ||
}); | ||
}); | ||
asyncTest('Send Document data',function(){ | ||
expect(1); | ||
qwest.post('tests/send_document/test.php',document) | ||
.then(function(response){ | ||
//console.log(response.debug); | ||
ok(response.status=='ok'); | ||
start(); | ||
}) | ||
.catch(function(message){ | ||
ok(false,message); | ||
start(); | ||
}); | ||
}); | ||
asyncTest('Send ArrayBuffer data',function(){ | ||
expect(1); | ||
var arrayBuffer=new Uint8Array([1,2,3]); | ||
qwest.post('tests/send_arraybuffer/test.php',arrayBuffer) | ||
.then(function(response){ | ||
//console.log(response.debug); | ||
ok(response.status=='ok'); | ||
start(); | ||
}) | ||
.catch(function(message){ | ||
ok(false,message); | ||
start(); | ||
}); | ||
}); | ||
}); |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
794158
41
3230
1
191
7