Javascript闭包:如何向Cesium map添加动态baselayers

时间:2016-12-22 19:24:04

标签: javascript closures cesium

我正在尝试从数据库中的一组值向Cesium映射添加多个baselayers。我想让javascript迭代它们然后添加它们。以下是Cesium的静态代码示例:

var imageryViewModels = [];
imageryViewModels.push(new Cesium.ProviderViewModel({
     name : 'Open\u00adStreet\u00adMap',
     iconUrl : Cesium.buildModuleUrl('openStreetMap.png'),
     tooltip : 'OpenStreetMap (OSM)',
     creationFunction : function() {
         return Cesium.createOpenStreetMapImageryProvider({
             url : 'https://a.tile.openstreetmap.org/'
         });
     }
 }));

 imageryViewModels.push(new Cesium.ProviderViewModel({
     name : 'Black Marble',
     iconUrl : Cesium.buildModuleUrl('blackMarble.png'),
     tooltip : 'outlines of civilization',
     creationFunction : function() {
         return Cesium.createTileMapServiceImageryProvider({
             url : 'https://cesiumjs.org/blackmarble',
             credit : 'B Observatory',
             flipXY : true
         });
     }
 }));

到目前为止超级简单,一组静态值。这是它变得棘手的地方,我想循环一组值,然后将ProviderViewModels推送到数组。像这样 -

var imageryViewModels = [];
baseLayers = HashOfValuesFromDatabase;
for(int i=0; i<baseLayers.length; i++{

  imageryViewModels.push(new Cesium.ProviderViewModel({
       name : baseLayers[i].name,
       iconUrl : Cesium.buildModuleUrl(baseLayers[i].iconUrl),
       tooltip : baseLayser[i].toolTip,
       creationFunction : function() {
           return Cesium.createOpenStreetMapImageryProvider({
               url : baseLayers[i].url   // ***** this value always the last value ****
           });
       }
   }));

}

问题是javascript闭包导致我出现问题,我的每个imageryViewModel都是baseLayer.url对象中的最后一个值。铯需要这个功能。有没有办法保持这个函数,但得到迭代的baseLayer.url的值?

2 个答案:

答案 0 :(得分:2)

请尝试这个(我还没试过):

var imageryViewModels = [];
baseLayers = HashOfValuesFromDatabase;
for(int i=0; i<baseLayers.length; i++{

  imageryViewModels.push(new Cesium.ProviderViewModel({
       name : baseLayers[i].name,
       iconUrl : Cesium.buildModuleUrl(baseLayers[i].iconUrl),
       tooltip : baseLayser[i].toolTip,
       creationFunction : (function(i) {
           return function() {
             return Cesium.createOpenStreetMapImageryProvider({
                 url : baseLayers[i].url  
             });
           }
       }(i))
   }));

}

编辑:正确的语法(感谢emackey)

答案 1 :(得分:2)

Ben Aston的答案是正确的方法。他没有尝试运行它,并且date(DATE_RFC822, time()); 在参数列表中非法的后面还有一个额外的分号,并且还有一些问题是他从原始文件中复制粘贴的题。这是更正后的版本,我确实让它运行:

class attendees: UIViewController, UITableViewDelegate, UITableViewDataSource, UISearchBarDelegate {

    var tableData = ""

    var value:String!

    var searchString = ""

    var firstname: [String] = []
    var lastname: [String] = []
    var fullname: [String] = []
    var company: [String] = []
    var jobtitle: [String] = []
    var image: [String] = []


    var filteredAppleProducts = [String]()
    var resultSearchController = UISearchController()

    @IBOutlet weak var tableView: UITableView!

    @IBOutlet weak var searchBar: UISearchBar!

    override func viewDidLoad() {

        print(value)



        searchBar.delegate = self



        self.tableView.reloadData()

        let nib = UINib(nibName: "vwTblCell2", bundle: nil)
        tableView.register(nib, forCellReuseIdentifier: "cell2")


    }

    override func viewDidAppear(_ animated: Bool) {
        getTableData()

    }


    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {


        if filteredAppleProducts != []{

            return self.filteredAppleProducts.count
        }
        else
        {

            if searchString != "[]" {
            return self.firstname.count
            }else {
                return 0
            }
        }

    }


    // 3
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell  {
        let cell2: TblCell2 = self.tableView.dequeueReusableCell(withIdentifier: "cell2") as! TblCell2

        print(filteredAppleProducts)


         if filteredAppleProducts != []{

            cell2.nameLabel.text = self.filteredAppleProducts[indexPath.row]

            return cell2
        }
        else
        {
            if searchString != "[]"{
            cell2.nameLabel.text = "\(self.firstname[indexPath.row]) \(self.lastname[indexPath.row])"
                cell2.companyLabel.text = self.company[indexPath.row]
                cell2.jobTitleLabel.text = self.jobtitle[indexPath.row]


                let url = URL(string: "https://www.asmserver.co.uk/wellpleased/backend/profileimages/\(self.image[indexPath.row])")
                let data = try? Data(contentsOf: url!) //make sure your image in this url does exist, otherwise unwrap in a if let check / try-catch
                cell2.userImage.image = UIImage(data: data!)

            }
            return cell2


        }
    }

    // 4
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

    }

    // 5
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 90
    }


    func updateSearchResults(){


        self.filteredAppleProducts.removeAll(keepingCapacity: false)

        let searchPredicate = NSPredicate(format: "SELF CONTAINS[c] %@", searchString)
        let array = (self.fullname as NSArray).filtered(using: searchPredicate)
        self.filteredAppleProducts = array as! [String]

        self.tableView.reloadData()

        print(filteredAppleProducts)


    }


    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
        print("searchText \(searchText)")
        print(filteredAppleProducts)

        searchString = searchText
         updateSearchResults()
           }

    func getTableData(){

        self.firstname.removeAll()
        self.lastname.removeAll()
        self.fullname.removeAll()
        self.company.removeAll()
        self.jobtitle.removeAll()
        self.image.removeAll()


        let defaults = UserDefaults()
        let userid = defaults.string(forKey: "id")

        let url = NSURL(string: "https://www.asmserver.co.uk/wellpleased/backend/searchattendees.php?userid=\(userid!)&eventid=\(value!)")

        print(url)

        let task = URLSession.shared.dataTask(with: url as! URL) { (data, response, error) -> Void in

            if let urlContent = data {

                do {

                    if let jsonResult = try JSONSerialization.jsonObject(with: urlContent, options: []) as? [[String:AnyObject]] {


                        var i = 0

                        while i < jsonResult.count {


                            self.firstname.append(jsonResult[i]["firstname"]! as! String)
                            self.lastname.append(jsonResult[i]["lastname"]! as! String)

                            let fname = jsonResult[i]["firstname"]! as! String
                            let lname = jsonResult[i]["lastname"]! as! String
                           let fullname1 = "\(fname) \(lname)"

                            self.fullname.append(fullname1)

                            self.company.append(jsonResult[i]["company"]! as! String)
                            self.jobtitle.append(jsonResult[i]["jobtitle"]! as! String)
                            self.image.append(jsonResult[i]["image"]! as! String)




                            i = i + 1

                        }

                    }

                } catch {

                    print("JSON serialization failed")

                }

            } else {

                print("ERROR FOUND HERE")
            }

            DispatchQueue.main.async(execute: { () -> Void in

                self.tableView.reloadData()

            })

            self.tableView.isUserInteractionEnabled = true
        }

        task.resume()

    }
}

修复}(i))参数的原因是因为使用var imageryViewModels = []; for(var i=0; i<baseLayers.length; i++) { imageryViewModels.push(new Cesium.ProviderViewModel({ name : baseLayers[i].name, iconUrl : Cesium.buildModuleUrl(baseLayers[i].iconUrl), tooltip : baseLayers[i].toolTip, creationFunction : (function(i) { return function() { return Cesium.createOpenStreetMapImageryProvider({ url : baseLayers[i].url }); }; }(i)) })); } 作为参数的IIFE(立即调用的函数表达式)。这通过循环每次迭代创建一个新的JavaScript闭包,这是昂贵的,但是是必需的,以便每个单独的url函数获得它自己的闭包,它具有自己的i值的副本循环的迭代。如果没有这个,只有一个只有一个create变量的闭包,当实际调用任何创建函数时,循环很长并且i的值已达到最大值