установить свойство модуля js с помощью вложенного обратного вызова - PullRequest
0 голосов
/ 18 января 2019

Я пытаюсь установить переменную / свойство модуля из вложенной функции (обычно это обратный вызов xhr (Api.get()) внутри этого модуля (в функции 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. Может кто-нибудь объяснить, почему и, если возможно, предоставить решение для установки свойства modules data внутри Api.get()?

1 Ответ

0 голосов
/ 18 января 2019

Вам нужно иметь ссылку на возвращаемый объект, чтобы вы могли изменить его свойство 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 */}. Это также будет работать как класс вместо простого объекта.

...