使用嵌套回调

时间:2019-01-18 17:01:39

标签: javascript module scope callback

我正在尝试通过该模块(在Api.get()函数中)中的嵌套函数(基本上是xhr回调(init())来设置模块变量/属性,但是它不起作用,我可以不知道为什么。

    //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。但是,console.log(data)方法内的init()记录了试图分配给Posts.data的对象的预期数组。回调中的data似乎是Posts.data之外的另一个变量。有人可以解释为什么,并且在可能的情况下提供一种在data内设置模块Api.get()属性的解决方案吗?

1 个答案:

答案 0 :(得分:1)

您需要引用返回对象,以便您在返回对象后更改其data属性。一种方法是使用方法和数据创建一个对象并返回该对象。然后,您可以使用data在内部引用其this.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 */}。这也可以作为类而不是普通对象使用。