TypeScript «это». не устанавливает объект

Я использую карты Bing v8 для геокодирования. сначала этого кода не было в классе. В итоге я добавил код в класс из-за этой ошибки:

typescript cannot redeclare block-scoped variable 'map'

Поскольку сейчас я использую класс, у меня проблемы с «этим». Прочитав об 'этом' в TypeScript, я я изменил свои функции, используя функции экземпляра (функции стрелки экземпляра):

/// <reference path="./../scripts/MicrosoftMaps/Microsoft.Maps.d.ts" />
/// <reference path="./../scripts/MicrosoftMaps/Modules/Search.d.ts" />
/// <reference path="./../scripts/typings/jquery/jquery.d.ts" />

class BMGeocode {

    map: Microsoft.Maps.Map;
    searchManager: Microsoft.Maps.Search.SearchManager;

    public loadMap = () => {
        this.map = new Microsoft.Maps.Map('#map', {
            credentials: 'xxx',
            center: new Microsoft.Maps.Location(51.087299, 2.976770),
            zoom: 10
        });
    }

    public search = () => {
        if (!this.searchManager) {
            Microsoft.Maps.loadModule('Microsoft.Maps.Search', function () {
                this.searchManager = new Microsoft.Maps.Search.SearchManager(this.map) ; // PROBLEM: searchManager is never set?
            });
        }

        // remove any previous results from the map.
        this.map.entities.clear();

        // get the users query and geocode it.
        let query: string = (<HTMLInputElement>document.getElementById("txtInput")).value;
        this.geocodeQuery(query);
    }

    private geocodeQuery = (query: string) => {
        var userData = { name: 'Maps Test User', id: 'XYZ' };
        let searchRequest: Microsoft.Maps.Search.IGeocodeRequestOptions = {
            where: query,
            userData: userData,
            count: 5,
            bounds: this.map.getBounds(),
            callback: function (r: any) {
                // PROBLEM: r undefined.
                if (r && r.results && r.results.length > 0) {
                    var topResult = r.results[0];
                    if (topResult) {
                        this.addPin(topResult.location);
                        $('#txtInput').focus().select();
                    }
                }
            },
            errorCallback: function (e: any) {
                // If there is an error, alert the user about it.
                alert("No results found.");
            }
        };

        // make the geocode request:
        this.searchManager.geocode(searchRequest);
    }

    // .. other stuff in class
}


let geo: BMGeocode = new BMGeocode();

function onGeocodeClick() {
    geo.search();
}

$(function() {
    geo.loadMap();
    $('#geocode').click(onGeocodeClick);
})

Я думаю, что обнаружил проблему, почему она не работает, так как searchManager всегда имеет значение null или undefined. Однако я не знаю, как это решить.

Эта строка из функции «поиск» работает, но, похоже, не устанавливает переменную searchManager:

this.searchManager = new Microsoft.Maps.Search.SearchManager(this.map);

searchManager не установлен, поэтому я не могу сделать запрос:

// make the geocode request:
    this.searchManager.geocode(searchRequest);

Как это можно решить в TypeScript?

Обновление: это тоже не работает:

public search = () => {
            if (!this.searchManager) {
                var self = this;
                Microsoft.Maps.loadModule('Microsoft.Maps.Search', function () {
                    self.searchManager = new Microsoft.Maps.Search.SearchManager(self.map); // PROBLEM!!
  self.search(); 
                });

            } else {

            // remove any previous results from the map.
            this.map.entities.clear();

            // get the users query and geocode it.
            let query: string = (<HTMLInputElement>document.getElementById("txtInput")).value;
            this.geocodeQuery(query);
        }

person juFo    schedule 23.11.2016    source источник
comment
Если serchManager действительно никогда не установлен, вы должны найти ошибку в консоли. Например, сетевая ошибка или выброшенное исключение во время загрузки модуля. С другой стороны, возможно, вам просто нужно подождать, так как функция загрузки модуля является асинхронной.   -  person Tamas Hegedus    schedule 23.11.2016
comment
я пытался вызвать рекурсию search(), когда searchManager не был установлен, но это также не сработало через this.search().   -  person juFo    schedule 23.11.2016
comment
Просто поставьте там точку останова и посмотрите, работает ли он this.searchManager = new Microsoft.Maps.Search.SearchManager(this.map) ;   -  person Tamas Hegedus    schedule 23.11.2016
comment
он попадает, но, похоже, он не устанавливает переменную searchManager из корня моего класса, поэтому, когда я позже вызываю функцию геокодирования, searchManager не определен.   -  person juFo    schedule 23.11.2016
comment
Чтобы избежать проблемы, с которой вы столкнулись, вам следует рассмотреть возможность использования флага noImplicitThis, который поможет отметить места, где вы можете потерять ссылку на this.   -  person Daniel Rosenwasser    schedule 23.11.2016


Ответы (1)


проблема в том, что переменная this относится не к BMGeocode, как можно было бы ожидать, а к закрытию, в котором вы пытаетесь ее использовать. Попробуйте это вместо этого:

var self = this
Microsoft.Maps.loadModule('Microsoft.Maps.Search', function () {
    self.searchManager = new Microsoft.Maps.Search.SearchManager(self.map) ; // PROBLEM: searchManager is never set?
});
person Lope    schedule 23.11.2016
comment
Это не относится к стрелочным функциям. - person Tamas Hegedus; 23.11.2016
comment
поиск - это стрелочная функция, но внутри loadModule есть замыкание, которого нет - person Lope; 23.11.2016
comment
@juFo Определенно должно работать. Ошибка все та же? - person Erik Cupal; 23.11.2016
comment
@juFo действительно создается объект? попробуйте сначала назначить его временной переменной и проверьте, не является ли она нулевой - person Lope; 23.11.2016