Javascript 不能';在对象中找不到脚本回调函数
我从谷歌使用,以设置与Spotify的连接。有一个问题。当Javascript 不能';在对象中找不到脚本回调函数,javascript,google-apps-script,oauth,callback,Javascript,Google Apps Script,Oauth,Callback,我从谷歌使用,以设置与Spotify的连接。有一个问题。当createService()和authCallback()是auth对象的一部分时,引发错误: 找不到脚本函数:authCallback() 为什么在auth对象中回调函数不可见 此案例的代码为: function doGet() { if (auth.hasAccess()) { main(); } else { return auth.createFlow(); } } co
createService()
和authCallback()
是auth
对象的一部分时,引发错误:
找不到脚本函数:authCallback()
为什么在auth对象中回调函数不可见
此案例的代码为:
function doGet() {
if (auth.hasAccess()) {
main();
} else {
return auth.createFlow();
}
}
const auth = (function () {
const CLIENT_ID = '...';
const CLIENT_SECRET = '...';
const _service = createService();
function createService() {
return OAuth2.createService('spotify')
.setAuthorizationBaseUrl('https://accounts.spotify.com/authorize')
.setTokenUrl('https://accounts.spotify.com/api/token')
.setClientId(CLIENT_ID)
.setClientSecret(CLIENT_SECRET)
.setCallbackFunction('authCallback') // set callback
.setPropertyStore(PropertiesService.getUserProperties())
.setScope('playlist-read-private playlist-modify-private playlist-modify-public user-library-read')
.setParam('response_type', 'code')
.setParam('redirect_uri', getRedirectUri());
}
function authCallback(request) {
let isAuthorized = _service.handleCallback(request);
if (isAuthorized) {
return HtmlService.createHtmlOutput('Success! You can close this tab.');
} else {
return HtmlService.createHtmlOutput('Denied. You can close this tab');
}
}
...
return {
hasAccess: hasAccess,
getAccessToken: getAccessToken,
createFlow: createFlow,
};
})();
但如果在没有auth
对象的情况下执行此操作,则不会出现错误和成功回调:
function createService() {
return OAuth2.createService('spotify')
.setCallbackFunction('authCallback')
// ...
}
function authCallback(request) {
// ...
}
我可以这样做,但是在auth
对象中隐藏实现细节是没有意义的:
const auth = (function () {
function createService() {
return OAuth2.createService('spotify')
.setCallbackFunction('authCallback')
// ...
}
function authCallback(request) {
// ...
}
return {
// ...
authCallback: authCallback,
};
})();
function authCallback(request) {
return auth.authCallback(request);
}
function doGet() {
if (auth.hasAccess()) {
main();
} else {
return auth.createFlow();
}
}
带错误的完整代码
函数doGet(){
if(auth.hasAccess()){
main();
}否则{
返回auth.createFlow();
}
}
常量auth=(函数(){
const CLIENT_ID='…';
const CLIENT_SECRET='…';
const_service=createService();
函数createService(){
返回OAuth2.createService('spotify')
.setAuthorizationBaseUrl('https://accounts.spotify.com/authorize')
.setTokenUrl('https://accounts.spotify.com/api/token')
.setClientId(客户端ID)
.setClientSecret(客户端密码)
.setCallbackFunction('authCallback')
.setPropertyStore(PropertiesService.getUserProperties())
.setScope('playlist-read-private playlist modify private playlist modify public user library read')
.setParam('响应类型','代码')
.setParam('redirect_uri',getRedirectUri());
}
函数authCallback(请求){
让isAuthorized=\u service.handleCallback(请求);
如果(未授权){
返回HtmlService.createHtmlOutput('成功!您可以关闭此选项卡');
}否则{
返回HtmlService.createHtmlOutput('Denied.youcan close this tab');
}
}
函数getRedirectUri(){
让scriptId=encodeURIComponent(ScriptApp.getScriptId());
让我们来看看https://script.google.com/macros/d/%s/usercallback';
返回Utilities.formatString(模板,scriptId);
}
函数hasAccess(){
return _service.hasAccess();
}
函数getAccessToken(){
return_service.getAccessToken();
}
函数createFlow(){
让模板=“”;
让html=Utilities.formatString(模板,_service.getAuthorizationUrl());
返回HtmlService.createHtmlOutput(html);
}
返回{
hasAccess:hasAccess,
getAccessToken:getAccessToken,
createFlow:createFlow,
};
})();
传递到setCallbackFunction()
的值实际上被传递到方法中,该方法不要求参数在全局范围内可用。但这意味着您需要传递字符串“auth.authCallback”。简单地将其传递为“authCallback”将不起作用,因为全局作用域中没有具有该名称的函数
因此,这也意味着您需要在return语句中公开authCallback
,以便它在全局范围内作为auth.authCallback
可用
const auth = (function () {
const CLIENT_ID = '...';
const CLIENT_SECRET = '...';
const _service = createService();
function createService() {
return OAuth2.createService('spotify')
.setAuthorizationBaseUrl('https://accounts.spotify.com/authorize')
.setTokenUrl('https://accounts.spotify.com/api/token')
.setClientId(CLIENT_ID)
.setClientSecret(CLIENT_SECRET)
.setCallbackFunction('auth.authCallback') // Use correct method name
.setPropertyStore(PropertiesService.getUserProperties())
.setScope('playlist-read-private playlist-modify-private playlist-modify-public user-library-read')
.setParam('response_type', 'code')
.setParam('redirect_uri', getRedirectUri());
}
function authCallback(request) {
let isAuthorized = _service.handleCallback(request);
if (isAuthorized) {
return HtmlService.createHtmlOutput('Success! You can close this tab.');
} else {
return HtmlService.createHtmlOutput('Denied. You can close this tab');
}
}
function getRedirectUri() {
let scriptId = encodeURIComponent(ScriptApp.getScriptId());
let template = 'https://script.google.com/macros/d/%s/usercallback';
return Utilities.formatString(template, scriptId);
}
function hasAccess() {
return _service.hasAccess();
}
function getAccessToken() {
return _service.getAccessToken();
}
function createFlow() {
let template = '<a href="%s" target="_blank">Authorize</a>';
let html = Utilities.formatString(template, _service.getAuthorizationUrl());
return HtmlService.createHtmlOutput(html);
}
return {
hasAccess: hasAccess,
getAccessToken: getAccessToken,
createFlow: createFlow,
authCallback: authCallback // Expose the method
};
})();
const auth=(函数(){
const CLIENT_ID='…';
const CLIENT_SECRET='…';
const_service=createService();
函数createService(){
返回OAuth2.createService('spotify')
.setAuthorizationBaseUrl('https://accounts.spotify.com/authorize')
.setTokenUrl('https://accounts.spotify.com/api/token')
.setClientId(客户端ID)
.setClientSecret(客户端密码)
.setCallbackFunction('auth.authCallback')//使用正确的方法名
.setPropertyStore(PropertiesService.getUserProperties())
.setScope('playlist-read-private playlist modify private playlist modify public user library read')
.setParam('响应类型','代码')
.setParam('redirect_uri',getRedirectUri());
}
函数authCallback(请求){
让isAuthorized=\u service.handleCallback(请求);
如果(未授权){
返回HtmlService.createHtmlOutput('成功!您可以关闭此选项卡');
}否则{
返回HtmlService.createHtmlOutput('Denied.youcan close this tab');
}
}
函数getRedirectUri(){
让scriptId=encodeURIComponent(ScriptApp.getScriptId());
让我们来看看https://script.google.com/macros/d/%s/usercallback';
返回Utilities.formatString(模板,scriptId);
}
函数hasAccess(){
return _service.hasAccess();
}
函数getAccessToken(){
return_service.getAccessToken();
}
函数createFlow(){
让模板=“”;
让html=Utilities.formatString(模板,_service.getAuthorizationUrl());
返回HtmlService.createHtmlOutput(html);
}
返回{
hasAccess:hasAccess,
getAccessToken:getAccessToken,
createFlow:createFlow,
authCallback:authCallback//公开该方法
};
})();
为了帮助澄清
authCallback()
的用途,请尝试将其重命名为类似于displayAuthSuccessOrFailure()
。它所做的只是向最终用户呈现一条成功或失败的消息。这可能会改变您对其公开/封装的看法。如果您在iLife
中不公开authCallback
,调用者如何调用它?你到底想对谁隐藏它?在对象内部声明authCallback
而不是在全局范围内这样做有什么好处?@Rubén封装:D请阅读
const auth = (function () {
const CLIENT_ID = '...';
const CLIENT_SECRET = '...';
const _service = createService();
function createService() {
return OAuth2.createService('spotify')
.setAuthorizationBaseUrl('https://accounts.spotify.com/authorize')
.setTokenUrl('https://accounts.spotify.com/api/token')
.setClientId(CLIENT_ID)
.setClientSecret(CLIENT_SECRET)
.setCallbackFunction('auth.authCallback') // Use correct method name
.setPropertyStore(PropertiesService.getUserProperties())
.setScope('playlist-read-private playlist-modify-private playlist-modify-public user-library-read')
.setParam('response_type', 'code')
.setParam('redirect_uri', getRedirectUri());
}
function authCallback(request) {
let isAuthorized = _service.handleCallback(request);
if (isAuthorized) {
return HtmlService.createHtmlOutput('Success! You can close this tab.');
} else {
return HtmlService.createHtmlOutput('Denied. You can close this tab');
}
}
function getRedirectUri() {
let scriptId = encodeURIComponent(ScriptApp.getScriptId());
let template = 'https://script.google.com/macros/d/%s/usercallback';
return Utilities.formatString(template, scriptId);
}
function hasAccess() {
return _service.hasAccess();
}
function getAccessToken() {
return _service.getAccessToken();
}
function createFlow() {
let template = '<a href="%s" target="_blank">Authorize</a>';
let html = Utilities.formatString(template, _service.getAuthorizationUrl());
return HtmlService.createHtmlOutput(html);
}
return {
hasAccess: hasAccess,
getAccessToken: getAccessToken,
createFlow: createFlow,
authCallback: authCallback // Expose the method
};
})();