Javascript JS中设置对象属性的异步操作问题
我正在为基于web的服务开发一个客户端库,在设置对象变量和以后检索它时遇到了一些问题 这是图书馆的开始Javascript JS中设置对象属性的异步操作问题,javascript,jquery,Javascript,Jquery,我正在为基于web的服务开发一个客户端库,在设置对象变量和以后检索它时遇到了一些问题 这是图书馆的开始 var QuickBase = function(username, password, apptoken, realm) { this.username = username; this.password = password; this.apptoken = (typeof apptoken === "undefined") ? '' : apptoken;
var QuickBase = function(username, password, apptoken, realm) {
this.username = username;
this.password = password;
this.apptoken = (typeof apptoken === "undefined") ? '' : apptoken;
this.realm = (typeof realm === "undefined") ? 'www' : realm;
this.ticket = '';
this.dbid = '';
this.payload = '<qdbapi>';
this.init = function() {
var self = this;
this.authenticate(this.username, this.password, null, null, function(data) {
var errcode = $(data).find('errcode').text();
if(errcode > 0)
throw new Error($(data).find('errtext').text());
self.ticket = $(data).find('ticket').text();
});
}
this.setBaseUrl = function() {
var endpoint = this.dbid == '' ? 'main' : this.dbid;
this.baseUrl = 'https://' + this.realm + '.quickbase.com/db/' + endpoint;
}
this.transmit = function(method, callback) {
this.setBaseUrl();
if(this.apptoken)
this.payload += '<apptoken>' + this.apptoken + '</apptoken>';
if(this.ticket)
this.payload += '<ticket>' + this.ticket + '</ticket>';
this.payload += '</qdbapi>';
console.log(this.payload);
$.ajax({
url: this.baseUrl,
type: 'POST',
data: this.payload,
dataType: 'xml',
headers: {
'Content-Type': 'application/xml',
'QUICKBASE-ACTION': method
},
success: callback
});
this.payload = '<qdbapi>';
}
this.addSettingsToPayload = function(settings) {
for(var key in settings) {
this.payload += '<' + key + '>' + settings[key] + '</' + key + '>';
}
}
this.authenticate = function(username, password, hours, udata, callback) {
this.payload += '<username>' + username + '</username>';
this.payload += '<password>' + password + '</password>';
this.payload += (typeof hours === "undefined") ? '' : '<hours>' + hours + '</hours>';
this.payload += (typeof udata === "undefined") ? '' : '<udata>' + udata + '</udata>';
this.transmit('API_Authenticate', callback);
}
所以我的问题是为什么qb.ticket没有被设置,并且在将来的函数调用中不可用
此外,是否有一种方法不必在.when中包装.init()
基本上,init设置了未来所有API方法都需要的票证。如果我只调用qb.init()然后调用qb.doQuery(),不能保证init()已经完成-但是如果我使用.when,这是否意味着所有未来的方法调用都需要在.then回调中完成?这看起来很难看。
$。当
需要承诺对象时。如果没有得到,它将立即执行回调。您必须从$.ajax
调用中返回承诺,或者创建自己的承诺
但既然你只做了一个承诺,你甚至不需要什么时候。你可以做:
qb.init().done(qb.doQuery.bind(qb));
例如:
var QuickBase = function(username, password, apptoken, realm) {
// ...
this.init = function() {
var self = this;
return this.authenticate(this.username, this.password, null, null).done(function(data) {
var errcode = $(data).find('errcode').text();
if(errcode > 0)
throw new Error($(data).find('errtext').text());
self.ticket = $(data).find('ticket').text();
});
}
this.transmit = function(method) {
// ...
var promise = $.ajax({
url: this.baseUrl,
type: 'POST',
data: this.payload,
dataType: 'xml',
headers: {
'Content-Type': 'application/xml',
'QUICKBASE-ACTION': method
}
});
this.payload = '<qdbapi>';
return promise;
}
this.authenticate = function(username, password, hours, udata) {
// ..
return this.transmit('API_Authenticate');
}
}
然后:
qb.init(function(){
qb.doQuery();
});
最简单的方法可能是从
init()
返回承诺,如下所示:
this.init = function() {
var self = this;
var dfrd = $.Deferred();
this.authenticate(this.username, this.password, null, null, function(data) {
var errcode = $(data).find('errcode').text();
if(errcode > 0)
throw new Error($(data).find('errtext').text());
self.ticket = $(data).find('ticket').text();
dfrd.resolve();
});
return dfrd.promise();
}
然后:
window.qb = new QuickBase(username, password, token, realm);
qb.init().then(function() {
console.log(qb);
console.log(qb.ticket);
qb.doQuery();
});
someMethod
可能在init
完成之前运行。把someMethod
移到闭包处,你会没事的。不太好。这并不能回答为什么console.log(s.ticket)返回空,而上面的输出显示它已被设置。请发布s.init的实现。添加了整个shebang。我们试图保持它的简单性,但是完整的示例可能更有用。在中没有发生任何事情。transmit
但是您完全终止了transmit接受为arg并用于调用的回调?我想我需要这样,例如,用户doQuery可以在返回数据时处理返回数据,不是吗?是吗?哪里你是说在传输
或验证
中?您不再需要回调
参数,因为您正在返回承诺。什么是承诺?我第一次听说这个概念。然后我想知道你为什么在开始时使用$。看看,也许吧。这是一次试图(尽管很糟糕)解决根本问题的尝试。使用这种方法,如果用户不能在成功时传入回调函数,那么用户如何知道何时说qb.doQuery返回?举个例子会很有帮助。
this.init = function() {
var self = this;
var dfrd = $.Deferred();
this.authenticate(this.username, this.password, null, null, function(data) {
var errcode = $(data).find('errcode').text();
if(errcode > 0)
throw new Error($(data).find('errtext').text());
self.ticket = $(data).find('ticket').text();
dfrd.resolve();
});
return dfrd.promise();
}
window.qb = new QuickBase(username, password, token, realm);
qb.init().then(function() {
console.log(qb);
console.log(qb.ticket);
qb.doQuery();
});