возврат данных из метода родительского контроллера после завершения функции обратного вызова - PullRequest
0 голосов
/ 28 апреля 2020

Я знаю, что подобные вопросы задавались, и я пытался понять их и применить к своей проблеме, но я пока не смог заставить что-то работать.

Следующий код является функцией контроллера Adonis. js.

Предполагается взять поисковый запрос и использовать API поиска Google (serpApi) для поиска по этому термину, а затем вернуть массив URL.

Однако на данный момент я могу получить только это к console.log 'links', но я хочу возвращать массив ссылок всякий раз, когда вызывается функция googleSearch.

     async googleSearch(searchTerm) {

        let client = new GSR.GoogleSearchResults("[MyApiKey]")

            var parameter = {
                q: `${searchTerm}`,
                hl: "en",
                gl: "us",
                google_domain: "google.com",
            };

            const callback = function(data) {
                let links = []; 
                for (let i = 0; i < data.organic_results.length; i++) {                       
                    links.push(data.organic_results[i].link)            
                }
              console.log(links)                                  
           }            

        client.json(parameter, callback)

        }

Я вижу нужные мне данные, когда я консольный журнал, из функции обратного вызова, однако я хочу вернуть эти данные при вызове родительской функции, а не записывать их в консоль.

Я знаю, что проблема лежит где-то в асинхронной / синхронной области, и я пытался выяснить, как реорганизовать обратный вызов и изменить порядок вещей, насколько я знаю, как, но, похоже, не могу понять, Работа.

Ниже приведен пример того, что я пытаюсь осуществить, очевидно, это не работает, но, возможно, это помогает прояснить ситуацию.

    async googleSearch(searchTerm) {

        let results= []
        let client = new GSR.GoogleSearchResults("[MyApiKey]")

            var parameter = {
                q: `${searchTerm}`,
                hl: "en",
                gl: "us",
                google_domain: "google.com",
            };

            const callback = await function(data) {
                let links = []; 
                for (let i = 0; i < data.organic_results.length; i++) {                       
                    links.push(data.organic_results[i].link)            
                }
              results.push(links)                                
           }            

        client.json(parameter, callback)
       return results 
        }

1 Ответ

0 голосов
/ 28 апреля 2020

Вариант 1.

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

Представьте свой метод googleSearch с Второй параметр, который будет функцией вашего родительского (вызывающего) компонента. Эта функция будет вызываться в текущем обратном вызове только вместо console.log (ссылки). Таким образом, вызывающий компонент не будет ожидать получения результата со ссылками, но родительский компонент получит асинхронный вызов предоставленной функции, когда ссылки будут готовы, они будут переданы в качестве параметра. Итак, давайте назовем эту функцию 'processLinks'.

googleSearch(searchTerm, processLinks) {

    let client = new GSR.GoogleSearchResults("[MyApiKey]")

        var parameter = {
            q: `${searchTerm}`,
            hl: "en",
            gl: "us",
            google_domain: "google.com",
        };

        const callback = function(data) {
            let links = []; 
            for (let i = 0; i < data.organic_results.length; i++) {                       
                links.push(data.organic_results[i].link)            
            }
          processLinks(links)                                  
       }            

    client.json(parameter, callback)

    }

Тогда родительский компонент вызовет что-то вроде:

onSearchTermChange(searchTerm){
  childComponent.googleSearch(searchTerm, this.processLinks);
},
processLinks(links){
  // Do whatever needed with the links.
}

Вариант 2.

Верхнее решение является своего рода реализация собственного механизма обещаний (не так круто, просто чтобы помочь вам понять принципы). Таким образом, второй вариант, вместо добавления функции processLinks в качестве параметра, заставляет googleSearch возвращать обещание. Конструктор Обещания принимает методы разрешения и отклонения в качестве лямбда-параметров (они будут снова использоваться в качестве обратных вызовов, но вместо объявления их как функции в родительском компоненте они являются частью Обещания. Вы можете использовать разрешение для передать данные обратно в родительский компонент и использовать reject, если что-то пойдет не так, и родитель не должен больше ждать результата. Давайте попробуем это с примером:

    googleSearch(searchTerm) {
      return new Promise ((resolve, reject) => {
         let client = new GSR.GoogleSearchResults("[MyApiKey]")

           var parameter = {
              q: `${searchTerm}`,
              hl: "en",
              gl: "us",
              google_domain: "google.com",
          };

          const callback = function(data) {
              let links = []; 
              for (let i = 0; i < data.organic_results.length; i++) {                       
                  links.push(data.organic_results[i].link)            
              }
              resolve(links)                                  
          }            

         client.json(parameter, callback) // TODO If this fails call reject(errorDetails);
      }); // The promise returned.     
    }

Тогда родительский сервис будет использовать возвращенный обещание указать, что делать, когда обещание выполнено. Это делается с помощью вызова then и передачи двух лямбд (один для успешного сценария, другой для обработки ошибок)

onSearchTermChange(searchTerm){
  childComponent.googleSearch(searchTerm, this.processLinks).then((links) => {
      // Here we are when the child component invoked 'resolve(links)'
    }, (error) => {
      // Well in upper example I dont use the error handled (and should). You can add it for example if your call to client.json fails for some reason.
    });
},

Я объяснил вам, что Вы нуждались, или эти два варианта действительно смутили вас больше? :) Пожалуйста, дайте мне знать.

...