You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript命名空间对象:this无法使用?异步调用如何返回值?

var CustomUtils = {
  _constPageID: 12345,
  // This is called with the results from from FB.getLoginStatus().
  _statusChangeCallback: function(response) {
    console.log('statusChangeCallback');
    console.log(response);
    var callback = function(data) {
      alert('callback: ' + data);
      //actually I want the data here to be the return value of my main function below (at the end)
    };
    if (response.status === 'connected') {
      // Logged into your app and Facebook.
      CustomUtils._getToken(callback);
    }
  },
  /* main function to get a token */
  getAndReturnToken: function() {
    $.ajaxSetup({ cache: true });
    $.getScript('https://connect.facebook.net/en_US/sdk.js', function(){
      FB.init({
        appId: '....appid......',
        autoLogAppEvents : true,
        xfbml : true,
        version: 'v3.0'
      });
      FB.getLoginStatus(CustomUtils._statusChangeCallback);
    });
  },
};
问题解答

1. 为什么替换成this会报错,_constPageID却能用?

这核心是JavaScript中this的指向规则在搞鬼。当你把CustomUtils._statusChangeCallback换成this._statusChangeCallback时,你只是把这个函数的引用传给了FB.getLoginStatus,但等Facebook SDK调用这个回调时,函数内部的this已经不再指向CustomUtils了——它的上下文变成了SDK内部的执行环境(非严格模式下甚至会变成全局window对象)。这时候this._statusChangeCallback自然找不到对应的方法,所以报错。

那为什么this._constPageID能正常用?因为你使用它的场景是在CustomUtils的方法内部直接访问,比如在getAndReturnToken里调用时,this确实指向CustomUtils(方法调用时,this默认指向调用该方法的对象)。

解决这个问题的常用方法有三种:

  • 用bind绑定this:手动把回调的this固定为CustomUtils,比如:
    FB.getLoginStatus(this._statusChangeCallback.bind(this));
    
  • 使用箭头函数:箭头函数会继承外层作用域的this,把_statusChangeCallback改成箭头函数后,内部的this会一直指向CustomUtils:
    _statusChangeCallback: (response) => {
      console.log('statusChangeCallback');
      console.log(response);
      // 这里的this始终指向CustomUtils
      // ...其他代码
    }
    
  • 提前保存this到变量:在getAndReturnToken里先把this存成self,后续回调里用这个变量代替this:
    getAndReturnToken: function() {
      const self = this;
      $.ajaxSetup({ cache: true });
      $.getScript('https://connect.facebook.net/en_US/sdk.js', function(){
        FB.init({/*...*/});
        FB.getLoginStatus(self._statusChangeCallback);
      });
    },
    

2. 异步函数如何返回token供其他代码使用?

异步操作的本质就是无法同步返回结果——getAndReturnToken会在AJAX和Facebook SDK的异步操作完成前就执行完毕,直接返回的话只能得到undefined。目前主流的解决方案有以下几种:

方案一:使用Promise(最推荐)

把getAndReturnToken改成返回一个Promise,当token获取成功时调用resolve传递token,失败时调用reject传递错误信息。其他代码可以用.then()或者async/await来获取token,写法更优雅:

修改后的核心代码示例:

var CustomUtils = {
  _constPageID: 12345,
  _statusChangeCallback: function(response, resolve, reject) {
    if (response.status === 'connected') {
      // 把_getToken也改成返回Promise
      this._getToken().then(token => {
        resolve(token);
      }).catch(err => {
        reject(err);
      });
    } else {
      reject(new Error('用户未登录Facebook'));
    }
  },
  _getToken: function() {
    return new Promise((resolve, reject) => {
      // 这里写获取token的异步逻辑,成功时resolve(token),失败时reject(err)
    });
  },
  getAndReturnToken: function() {
    return new Promise((resolve, reject) => {
      $.ajaxSetup({ cache: true });
      $.getScript('https://connect.facebook.net/en_US/sdk.js', () => {
        FB.init({
          appId: '....appid......',
          autoLogAppEvents : true,
          xfbml : true,
          version: 'v3.0'
        });
        FB.getLoginStatus((response) => {
          this._statusChangeCallback(response, resolve, reject);
        }.bind(this));
      });
    });
  },
};

使用方式:

// 用then/catch链式调用
CustomUtils.getAndReturnToken().then(token => {
  // 拿到token后执行后续API调用
  console.log('获取到的token:', token);
}).catch(err => {
  console.error('获取token失败:', err);
});

// 或者在async函数里用await(更像同步写法)
async function fetchDataWithToken() {
  try {
    const token = await CustomUtils.getAndReturnToken();
    console.log('获取到的token:', token);
    // 后续依赖token的操作
  } catch (err) {
    console.error('出错了:', err);
  }
}

方案二:使用回调函数(传统方式)

虽然你不想在回调里写后续逻辑,但这是早期JS处理异步的标准方式。可以把后续逻辑封装成函数,作为参数传给getAndReturnToken,等token获取到后再调用这个函数:

getAndReturnToken: function(onSuccess, onError) {
  $.ajaxSetup({ cache: true });
  $.getScript('https://connect.facebook.net/en_US/sdk.js', () => {
    FB.init({/*...*/});
    FB.getLoginStatus((response) => {
      if (response.status === 'connected') {
        this._getToken((token) => {
          onSuccess(token);
        }, onError);
      } else {
        onError(new Error('用户未登录'));
      }
    }.bind(this));
  });
},

使用方式:

CustomUtils.getAndReturnToken((token) => {
  // 拿到token执行后续操作
}, (err) => {
  // 处理错误
});

内容的提问来源于stack exchange,提问作者rishijd

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:02:31