问题
How do I time out a XMLHttpRequest in QML? I have the following code, but it won't time out. It seems the timeout functionality is not implemented!? Is there any other way to achieve timeouts?
var http = new XMLHttpRequest();
http.open("POST", "http://localhost/test.xml", true);
http.setRequestHeader('Content-type', 'application/json; charset=utf-8')
http.timeout = 4000;
http.ontimeout = function () {
console.log("timed out")
}
http.onreadystatechange = function() {
if (http.readyState === XMLHttpRequest.DONE) {
// Do something
}
}
http.send(JSON.stringify(data));
Edit: The code is not in a qml, but in a js file. And it won't go into a qml file as it is part of the model (MVC).
回答1:
It looks that QML XMLHttpRequest does not support timeout function.
This is a list of supported subset of functions/properties:
http://qt-project.org/doc/qt-5/qtqml-javascript-qmlglobalobject.html#xmlhttprequest
But you can use QML Timer item for this purposes, for example:
import QtQuick 2.3
Item {
id: root
width: 600
height: 400
Text {
anchors.fill: parent
id: response
text: "Click me"
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
MouseArea {
anchors.fill: parent
onClicked: {
response.text = "Loading...";
var req = new XMLHttpRequest();
var timer = Qt.createQmlObject("import QtQuick 2.3; Timer {interval: 4000; repeat: false; running: true;}",root,"MyTimer");
timer.triggered.connect(function(){
req.abort();
response.text = "timed out";
});
req.open("GET","http://google.com--",true); // correct me
req.onreadystatechange = function() {
if (req.readyState === XMLHttpRequest.DONE && req.status == 200) {
response.text = req.getAllResponseHeaders();
timer.running = false;
}
}
req.send();
}
}
}
}
回答2:
A global setTimeout() and setInterval() utility that models the functionality found in browsers.
It can be used to indirectly timeout an XMLHttpRequest. Or used sparingly elsewhere within the application.
timeoutId = util.timer.setTimeout(function() {}, 4500);
util.timer.clearInterval(timeoutId);
Main QML Snippet
With the following code, any child is able to access the methods under the app.util.timer namespace (or util.timer namespace if JS code is loaded in the main codebehind file).
import "CodeBehind.js" as CodeBehind
id: appWindow
QtObject {
id: app
property var util: CodeBehind.util
}
Component.onCompleted: {
CodeBehind.util.timer.init(appWindow);
}
CodeBehind JS Snippet
var util = util || {};
Qt.include("qrc:/Util/Timer.js");
Utility JS File
var util = util || {};
/**
Mimics the window.setTimeout() and window.setInterval() functionality
found in browsers.
@namespace timer
@memberof util
*/
util.timer = new function() {
var _timer;
var _timerList = [];
var _currentTime = 0;
var _api = {};
var _private = {};
var _enums = {};
/*************** Private ENUMS ***************/
_enums.type = {
timeout: 0,
interval: 1
};
/*************** Public API Methods ***************/
/**
Mimics the window.setTimeout() functionality found in browsers.
@param {function} callback
@param {int} interval Milliseconds
@public
@memberof util.timer
*/
_api.setTimeout = function(callback, interval) {
var timer, id;
id = parseInt(Math.random() * Date.now());
timer = new Timer(id, callback, interval, _enums.type.timeout);
_timerList.push({ id: id, timer: timer });
return id;
};
/**
Mimics the window.setInterval() functionality found in browsers.
@param {function} callback
@param {int} interval Milliseconds
@public
@memberof util.timer
*/
_api.setInterval = function(callback, interval) {
var timer, id;
id = parseInt(Math.random() * Date.now());
timer = new Timer(id, callback, interval, _enums.type.interval);
_timerList.push({ id: id, timer: timer });
return id;
};
/**
Clears an interval or timout by the interval id that is returned
when setTimeout() or setInterval() is called.
@param {int} intervalId
@public
@memberof util.timer
*/
_api.clearInterval = function(intervalId) {
var idx, len, idxOfTimer;
if (_timerList) {
// Find the index of the timer
len = _timerList.length;
for (idx = 0; idx < len; idx++) {
if (_timerList[idx].id === intervalId) {
idxOfTimer = idx;
break;
}
}
// Remove the timer from the array
_timerList.splice(idxOfTimer, 1);
}
// If: There are no more timers in the timer list
// Then: Stop the QML timer element
if (!_timerList || _timerList.length === 0) {
_private.stop();
}
};
/*************** Private Helper Methods ***************/
_private.start = function() {
_timer.start();
};
_private.stop = function() {
_timer.stop();
_currentTime = 0;
};
_private.runInterval = function() {
var idx, len, tempList;
// Increment the current timer
_currentTime++;
if (_timerList) {
// Create a temp list of timers
tempList = [];
len = _timerList.length;
for (idx = 0; idx < len; idx++) {
tempList.push(_timerList[idx].timer);
}
// Trigger each method
len = tempList.length;
for (idx = 0; idx < len; idx++) {
tempList[idx].trigger();
}
}
};
/*************** Objects ***************/
/**
A timer object contains a trigger to check and see if it needs
to run the callback.
@param {int} id
@param {function} callback
@param {int} interval Milliseconds
@param {enum} type type.interval | type.timeout
@public
@memberof util.timer
*/
var Timer = function(id, callback, interval, type) {
var _obj = {};
_obj.api = {};
_obj.hasRun = false;
_obj.endTime = _currentTime + interval;
_obj.api.trigger = function() {
if (_currentTime >= _obj.endTime && !_api.hasRun) {
_obj.hasRun = true;
callback();
if (type === _enums.type.interval) {
_obj.endTime += interval;
_api.hasRun = false;
}
else {
_api.clearInterval(id);
}
}
};
_private.start();
return _obj.api;
};
/*************** Initialize ***************/
_api.init = function(appWindow) {
_timer = Qt.createQmlObject("import QtQuick 2.3; Timer { interval: 1; repeat: true; running: false;}", appWindow, "timer");
_timer.triggered.connect(_private.runInterval);
};
return _api;
};
来源:https://stackoverflow.com/questions/26598404/timeout-xmlhttprequest-in-qml