【问题标题】:set property of js module with nested callback使用嵌套回调设置 js 模块的属性
【发布时间】:2019-01-18 17:01:38
【问题描述】:

我试图从该模块(在init() 函数中)内的嵌套函数(基本上是一个 xhr 回调 (Api.get()) 设置模块变量/属性,但它不起作用,我不知道为什么.

    //posts
    var Posts = (function() {
            //array of all posts objects
        var data = null;

        //initialize the posts module
        var init = function(callback) {

            if(data === null) {
                //load all posts
                loadAll(function(response){
                    // data = JSON.parse(response)

                    var posts = JSON.parse(response)
                    //create array
                    data = posts;
                    // call callback
                    console.log(data)
                    callback()

                })
            }
        }
        // return all posts from api as json
        var loadAll = function(callback) {
            Api.get('/api/posts/get', function(response) {
                callback(response)
            })
        }


        //public interface
        return {
            data: data,
            init: init,
            loadAll: loadAll
        }
    })();

调用Posts.init() 后,我将Posts.data 登录到控制台,但它仍然是null。但是,init() 方法中的console.log(data) 记录了我试图分配给Posts.data 的预期对象数组。似乎回调中的dataPosts.data 之外的另一个变量。有人可以解释一下原因吗?如果可能的话,提供一个解决方案来在Api.get() 中设置模块data 属性?

【问题讨论】:

  • 您返回的对象有一个指向null 的数据属性。稍后更改 data 变量,不会更改返回对象中的值。

标签: javascript module scope callback


【解决方案1】:

您需要对返回对象有一个引用,以便在返回对象后更改其data 属性。一种方法是使用方法和数据创建一个对象并返回该对象。然后你可以在内部使用this.data 引用它的data 属性:

// Fake API
let Api = {
  get(url, cb) {
    cb('["testdata"]')
  }
}

//posts
var Posts = (function() {
  //array of all posts objects
  return {
    data: null,
    init(callback) {
      if (this.data === null) {
        //load all posts
        this.loadAll((response) => {       // arrow function needed here for correct `this` binding
          var posts = JSON.parse(response)

          //create array
          this.data = posts;  // add data
          callback()
        })
      }
    },
    loadAll(callback) {
      Api.get('/api/posts/get', function(response) {
        callback(response)
      })
    }
  }
})();

console.log("initial posts data: ", Posts.data)
Posts.init(() => console.log("After init():", Posts.data))

如果您这样做,则实际上不需要 IEFE,除非您计划制作多个对象。您可以使用Posts = {/* rest of the data and methods */}。这也可以作为类而不是普通对象工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-05-19
    • 2013-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-25
    • 1970-01-01
    相关资源
    最近更新 更多