【问题标题】:returning data from a parent controller method after a callback function has completed回调函数完成后从父控制器方法返回数据
【发布时间】:2020-08-12 10:58:41
【问题描述】:

我知道有人问过类似的问题,我已经尝试理解它们并将其应用于我自己的问题,但我还没有能够使任何事情发挥作用。

以下代码是 Adonis.js 控制器中的一个函数。

它应该获取一个搜索词并使用 Google 搜索 API (serpApi) 搜索该词,然后返回一个 URL 数组。

但是,目前我只能将它发送到 console.log 的“链接”,但我想在调用函数“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 
        }

【问题讨论】:

    标签: javascript node.js asynchronous callback adonis.js


    【解决方案1】:

    变体 1。

    尝试从“等到”的心态转变,最好把它想象成“完成后告诉我”。

    想象您的方法 googleSearch 带有第二个参数,该参数将是您的父(调用)组件提供的函数。此函数将在当前回调中调用,而不是在 console.log(links) 中调用。这样调用组件就不会等到收到带有链接的结果,而是父组件会在链接准备好时接收到提供的函数的异步调用,并将它们作为参数传递。所以我们称这个函数为“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 返回一个承诺。 Promise 的构造函数接受 resolve 和 reject 方法作为 lambda 参数(它们将再次用作回调,但不是将它们声明为父组件中的函数,而是 Promise 的一部分。您可以使用 resolve 来将数据传回父组件,如果出现问题,则使用拒绝,父组件不应再等待结果。举个例子:

        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' 并传递两个 lambdas 完成的(一个用于成功场景,一个用于错误处理)

    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.
        });
    },
    

    我是否向您解释了您需要什么,或者这两种变体实际上让您更加困惑? :) 请告诉我。

    【讨论】:

      猜你喜欢
      • 2012-05-25
      • 1970-01-01
      • 1970-01-01
      • 2020-07-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-28
      相关资源
      最近更新 更多