当函数自己调用时,对象的方法可以在函数中调用,但是当通过 setTimeout 调用函数时,对象是未定义的
Object's method can be called in function when function is called on its own, but when function called via setTimeout the object is undefined
我有以下 class Conference
:
//UrlSerializer is for encoding JSON objects into GET url
const UrlSerializer=require('./urlSerializer');
class Conference{
constructor(client,workspace){
this.client=client;
this.workspace=workspace;
this.urlSerializer=new UrlSerializer();
}
announce(conferenceSid,timeRemaining){
var parameters={
timeRemaining:timeRemaining
}
var url=this.urlSerializer.serialize('conferenceAnnounceTime',parameters);
console.log("conference.announce url: "+url);
this.client.conferences(conferenceSid)
.update({
announceUrl:url,
announceMethod:'GET'
})
.then(conference=>console.log(conference.friendlyName));
}
setTimedAnnounce(initialMinutes,minutesToElapse,conferenceSid){
var minutesRemaining=initialMinutes-minutesToElapse;
setTimeout(this.announce,minutesToElapse*60000,minutesRemaining);
}
}
module.exports=Conference;
UrlSerializer
是:
const querystring=require('querystring');
require('env2')('.env');
class UrlSerializer{
constructor(){
this.paramArrayName="parameters";
}
serialize(endpoint,paramArray){
var url=process.env.APP_BASE_URL+"/"+endpoint;
console.log("urlSerializer base url: "+url);
var arrayString=JSON.stringify(paramArray);
console.log("urlSerializer stringified parameter array: "+arrayString);
var fullUrl=url+"?"+querystring.stringify({[this.paramArrayName]:arrayString});
console.log("urlSerializer full url: "+fullUrl);
return fullUrl;
}
}
module.exports=UrlSerializer;
我从另一个模块 server
中的 Express 端点调用 conference
函数,如下所示:
app.get('/conferenceEvents',function(req,res){
conferenceSid=req.query.ConferenceSid;
conference.announce(conferenceSid,initialMinutes);
conference.setTimedAnnounce(initialMinutes,0.25,conferenceSid);
res.type('application/json');
res.status(200).send();
});
调用 conference.announce
成功,控制台输出:
urlSerializer base url: http://x.ngrok.io/conferenceAnnounceTime
urlSerializer stringified parameter array: {"timeRemaining":5}
urlSerializer full url: http://x.ngrok.io/conferenceAnnounceTime?parameters=%7B%22timeRemaining%22%3A5%7D
conference.announce url: http://x.ngrok.io/conferenceAnnounceTime?parameters=%7B%22timeRemaining%22%3A5%7D
但是当调用 conference.setTimedAnnounce()
后 15 秒过去时,我得到以下错误:
TypeError: Cannot read property 'serialize' of undefined
at Timeout.announce [as _onTimeout] (c:\thisAppPath\conference.js:45:30)
at ontimeout (timers.js:502:15)
at tryOnTimeout (timers.js:323:5)
at Timer.listOnTimeout (timers.js:290:5)
我在想也许当计时器调用 announce
时,它是以 urlSerializer
实例超出范围的方式进行的。当通过 setTimeout()
调用 announce
时,如何让它识别 urlSerializer
?
编辑:我尝试按如下方式保存 this
范围:
setTimedAnnounce(initialMinutes,minutesToElapse,conferenceSid){
var that=this;
var minutesRemaining=initialMinutes-minutesToElapse;
setTimeout(that.announce,minutesToElapse*60000,minutesRemaining);
}
但这给了我同样的错误。
编辑 2:
我使用了 Barmar 的 this.announce.bind(this)
解决方案并解决了 TypeError
,但是参数数组和 URL 在 announce 的 setTimeout() 调用中没有正确构造;控制台输出如下:
urlSerializer base url: http://x.ngrok.io/conferenceAnnounceTime
urlSerializer stringified parameter array: {}
urlSerializer full url: http://x.ngrok.io/conferenceAnnounceTime?parameters=%7B%7D
conference.announce url: http://x.ngrok.io/conferenceAnnounceTime?parameters=%7B%7D
我怀疑我需要在其他地方使用 .bind(this)
以便 urlSerializer.serialize()
会在适当的范围内用 this
被调用,但我还没有找到它还。
编辑 3:
没关系,我想通了——setTimeout
需要将 conferenceSid
作为参数传入以及 minutesRemaining
。现在工作。
setTimeout(this.announce,minutesToElapse*60000,minutesRemaining);
需要
setTimeout(this.announce.bind(this),minutesToElapse*60000,minutesRemaining);
将函数 属性 作为参数传递不会绑定 this
上下文。它仅在您使用该语法调用方法时自动绑定。
我有以下 class Conference
:
//UrlSerializer is for encoding JSON objects into GET url
const UrlSerializer=require('./urlSerializer');
class Conference{
constructor(client,workspace){
this.client=client;
this.workspace=workspace;
this.urlSerializer=new UrlSerializer();
}
announce(conferenceSid,timeRemaining){
var parameters={
timeRemaining:timeRemaining
}
var url=this.urlSerializer.serialize('conferenceAnnounceTime',parameters);
console.log("conference.announce url: "+url);
this.client.conferences(conferenceSid)
.update({
announceUrl:url,
announceMethod:'GET'
})
.then(conference=>console.log(conference.friendlyName));
}
setTimedAnnounce(initialMinutes,minutesToElapse,conferenceSid){
var minutesRemaining=initialMinutes-minutesToElapse;
setTimeout(this.announce,minutesToElapse*60000,minutesRemaining);
}
}
module.exports=Conference;
UrlSerializer
是:
const querystring=require('querystring');
require('env2')('.env');
class UrlSerializer{
constructor(){
this.paramArrayName="parameters";
}
serialize(endpoint,paramArray){
var url=process.env.APP_BASE_URL+"/"+endpoint;
console.log("urlSerializer base url: "+url);
var arrayString=JSON.stringify(paramArray);
console.log("urlSerializer stringified parameter array: "+arrayString);
var fullUrl=url+"?"+querystring.stringify({[this.paramArrayName]:arrayString});
console.log("urlSerializer full url: "+fullUrl);
return fullUrl;
}
}
module.exports=UrlSerializer;
我从另一个模块 server
中的 Express 端点调用 conference
函数,如下所示:
app.get('/conferenceEvents',function(req,res){
conferenceSid=req.query.ConferenceSid;
conference.announce(conferenceSid,initialMinutes);
conference.setTimedAnnounce(initialMinutes,0.25,conferenceSid);
res.type('application/json');
res.status(200).send();
});
调用 conference.announce
成功,控制台输出:
urlSerializer base url: http://x.ngrok.io/conferenceAnnounceTime
urlSerializer stringified parameter array: {"timeRemaining":5}
urlSerializer full url: http://x.ngrok.io/conferenceAnnounceTime?parameters=%7B%22timeRemaining%22%3A5%7D
conference.announce url: http://x.ngrok.io/conferenceAnnounceTime?parameters=%7B%22timeRemaining%22%3A5%7D
但是当调用 conference.setTimedAnnounce()
后 15 秒过去时,我得到以下错误:
TypeError: Cannot read property 'serialize' of undefined
at Timeout.announce [as _onTimeout] (c:\thisAppPath\conference.js:45:30)
at ontimeout (timers.js:502:15)
at tryOnTimeout (timers.js:323:5)
at Timer.listOnTimeout (timers.js:290:5)
我在想也许当计时器调用 announce
时,它是以 urlSerializer
实例超出范围的方式进行的。当通过 setTimeout()
调用 announce
时,如何让它识别 urlSerializer
?
编辑:我尝试按如下方式保存 this
范围:
setTimedAnnounce(initialMinutes,minutesToElapse,conferenceSid){
var that=this;
var minutesRemaining=initialMinutes-minutesToElapse;
setTimeout(that.announce,minutesToElapse*60000,minutesRemaining);
}
但这给了我同样的错误。
编辑 2:
我使用了 Barmar 的 this.announce.bind(this)
解决方案并解决了 TypeError
,但是参数数组和 URL 在 announce 的 setTimeout() 调用中没有正确构造;控制台输出如下:
urlSerializer base url: http://x.ngrok.io/conferenceAnnounceTime
urlSerializer stringified parameter array: {}
urlSerializer full url: http://x.ngrok.io/conferenceAnnounceTime?parameters=%7B%7D
conference.announce url: http://x.ngrok.io/conferenceAnnounceTime?parameters=%7B%7D
我怀疑我需要在其他地方使用 .bind(this)
以便 urlSerializer.serialize()
会在适当的范围内用 this
被调用,但我还没有找到它还。
编辑 3:
没关系,我想通了——setTimeout
需要将 conferenceSid
作为参数传入以及 minutesRemaining
。现在工作。
setTimeout(this.announce,minutesToElapse*60000,minutesRemaining);
需要
setTimeout(this.announce.bind(this),minutesToElapse*60000,minutesRemaining);
将函数 属性 作为参数传递不会绑定 this
上下文。它仅在您使用该语法调用方法时自动绑定。