1

I need some help with able to return back myArray from the function call seachResults2. When I do a console log the compiler tells me it cant find myArray. I want to be able to return myArray to the caller.

const searchResults2 = (query: string) => {
    const subscriptionKeyCredential = new atlasService.SubscriptionKeyCredential(
      "SUBSCRIPTION"
    );
    const pipeline = atlasService.MapsURL.newPipeline(subscriptionKeyCredential);
    const searchURL = new atlasService.SearchURL(pipeline);
    searchURL
      .searchAddress(atlasService.Aborter.timeout(10000), query)
      .then((response) => {
        const data2 = response.geojson.getFeatures();
       
        const myArray = new Array(data2.features.length)
          .fill(0)
          .map((item, idx) => {
            const category: string = data2.features[idx].id as string;
            return {
              value: category,
              label: labelElement(query, category),
            };
          });
      });
   console.log(myArray);  // Cannot find name 'myArray'
   //return myArray  cant do since its not accessable.
  };

const labelElement = (query: string, category: string) => {
    return (
      <div
        style={{
          display: "flex",
          justifyContent: "space-between",
        }}
      >
        <span>
          Found {query} on <a>{category}</a>
        </span>
        <span>{getRandomInt(200, 100)} results</span>
      </div>
    );
    }

And its been called like this.

 const [options, setOptions] = useState<SelectProps<unknown>["options"]>([]);

  const handleSearch = (value: string) => {
    setOptions(value ? searchResults2(value) : []);
  };

This is a question regarding scope of variables.

Sarah
  • 1,199
  • 2
  • 21
  • 42
  • I dont think this is a asynch call issue, its more of a variable declaration scope issue. Array is getting its length assigned inside geojson call. I need help in declaring the myarray outside the call, assign the length of myarray inside the call, fill the array inside the call and then make it available outside the geojson call. – Sarah Aug 01 '20 at 00:49

2 Answers2

1

myArray variable is not reachable when you tried to log it, you logged it out of its scope

const searchResults2 = async (query: string) => {
        const subscriptionKeyCredential = new atlasService.SubscriptionKeyCredential(
          "SUBSCRIPTION"
        );
        const pipeline = atlasService.MapsURL.newPipeline(subscriptionKeyCredential);
        const searchURL = new atlasService.SearchURL(pipeline);
        let myArray;
        let response = await searchURL.searchAddress(atlasService.Aborter.timeout(10000), query);
        const data2 = response.geojson.getFeatures();
        myArray = new Array(data2.features.length)
            .fill(0)
            .map((item, idx) => {
                const category: string = data2.features[idx].id as string;
                return {
                  value: category,
                  label: labelElement(query, category),
                };
              }); 
       console.log(myArray);  
      };
    
    const labelElement = (query: string, category: string) => {
        return (
          <div
            style={{
              display: "flex",
              justifyContent: "space-between",
            }}
          >
            <span>
              Found {query} on <a>{category}</a>
            </span>
            <span>{getRandomInt(200, 100)} results</span>
          </div>
        );
        }
user2222
  • 444
  • 2
  • 8
  • 18
  • Thanks User222, yes that is what I thought but couldnt figure it out how to make it work. Checking with your answer now.. will get back to you in a few minutes after checking it. – Sarah Aug 01 '20 at 00:53
  • humm, the array is empty at this level. Inside the scope it has values. Line after outside has myArray empty and line after inside has values. console.log("inside"); console.log(myArray); }); console.log("outside"); console.log(myArray); // Cannot find name 'myArray' //return myArray cant do since its not accessable. }; – Sarah Aug 01 '20 at 00:59
  • searchURL is a promise (asynchronous) so the promise and the console.log are executing in same time. When you arrive at console.log statement the array is not yet filled. you need to use async await – user2222 Aug 01 '20 at 01:09
  • Thanks so much @user222, see my answer below to Slawa, after I use the asyn promise.. The calling function does not like it. Here is the error it gives Type 'Promise<{ value: string; label: Element; }[]>' is not assignable to type 'SetStateAction'. – Sarah Aug 01 '20 at 01:17
  • 1
    i've updated my response, check it please – user2222 Aug 01 '20 at 01:20
  • checking now, did you get a chance to see that setStateAction cant have promise returned? – Sarah Aug 01 '20 at 01:33
  • Thanks @User222, it works great within the function but I need to be able to send the results back to the caller setOptions(value ? searchResults2(value) : []); and is not expecting a promise back. – Sarah Aug 01 '20 at 01:44
  • searchResults2 is not a promise, try return myArray after logging the value – user2222 Aug 01 '20 at 01:47
  • searchResults2 has an async in its function signature and so when its called this is what is showing Promise {}__proto__: Promise[[PromiseStatus]]: "fulfilled"[[PromiseValue]]: undefined – Sarah Aug 01 '20 at 02:00
  • 1
    when you called it use await as well await searchResults2() and async in the calling function – user2222 Aug 01 '20 at 02:05
  • ok trying that.. – Sarah Aug 01 '20 at 02:11
  • 1
    Thank you soooooo much, const handleSearch = async (value: string) => { setOptions(value ? await searchResults2(value) : []); }; did the trick.. I wish I had a way to give you 10 stars... Thank you, thank you sooo much. – Sarah Aug 01 '20 at 02:22
1

You can try to use async/away in this case and return myArray from one of the Promises, it will be automatically wrapped in the Promise

const searchResults2 = async (query: string) => {
    const subscriptionKeyCredential = new atlasService.SubscriptionKeyCredential(
        "SUBSCRIPTION"
    );
    const pipeline = atlasService.MapsURL.newPipeline(subscriptionKeyCredential);
    const searchURL = new atlasService.SearchURL(pipeline);
    let myArray = await searchURL
            .searchAddress(atlasService.Aborter.timeout(10000), query)
        .then((response) => {
            const data2 = response.geojson.getFeatures();

            return new Array(data2.features.length)
                .fill(0)
                .map((item, idx) => {
                    const category: string = data2.features[idx].id as string;
                    return {
                        value: category,
                        label: labelElement(query, category),
                    };
                }); // you can keep it as const but log it in this level
        });
        
        
    console.log(myArray); 
};
Slawa Eremin
  • 5,264
  • 18
  • 28
  • Thanks Slawa, trying that right now,.. will get back in 5 minutes after trying this.. – Sarah Aug 01 '20 at 01:08
  • ok So it is available outside in the function now, but its coming as a Promise {} to the calling function. See in the post when the call gets made setOptions(value ? searchResults2(value) : []); it gives a red squigly line with error :Type 'Promise<{ value: string; label: Element; }[]>' is not assignable to type 'SetStateAction'. – Sarah Aug 01 '20 at 01:16