无法 Return JSON 来自 NestJS 的数据 API

Unable to Return JSON Data from NestJS API

我正在构建一个 NestJS API,它将调用 Bing 的自定义搜索引擎端点和 return JSON 格式的搜索结果。 https://docs.microsoft.com/en-us/azure/cognitive-services/bing-custom-search/call-endpoint-nodejs

我能够使用我的 API 键成功调用端点并将结果 JSON 打印到我的控制台。我遇到的问题是函数 return 在请求有机会用任何数据填充数组之前使用空数据。

如果代码格式完全错误或整个设置不正确,我深表歉意。我以前从未编程过 API,必须即时学习。

控制器

import { Controller, Get } from '@nestjs/common';
import { SearchEngineService } from './search-engine.service';

@Controller('tasks') 
export class SearchEngineController {
    constructor(private searchEngineService: SearchEngineService) {}

    @Get()
    processRequest() {
        return this.searchEngineService.processRequest();
    }
}

服务

import { Injectable } from '@nestjs/common';

@Injectable()
export class SearchEngineService {
    processRequest() {
        var request = require("request"); 
        var searchResponse;
        var webPage;
        var parsedSearchResponse = [];
        var subscriptionKey = "SUBSCRIPTION_KEY";
        var customConfigId = "CONFIG_ID";
        var searchTerm = "partner";

        var info = {
            url: 'https://api.cognitive.microsoft.com/bingcustomsearch/v7.0/search?' 
                + 'q=' 
                + searchTerm 
                + "&" 
                + 'customconfig=' 
                + customConfigId,
            headers: {
                'Ocp-Apim-Subscription-Key' : subscriptionKey
            }
        }

        request(info, function(error, response, body) {
            searchResponse = JSON.parse(body);
            console.log("\n");
            for (var i = 0; i < searchResponse.webPages.value.length; ++i) {
                webPage = searchResponse.webPages.value[i];
                parsedSearchResponse.push(searchResponse.webPages.value[i]);
            
                console.log('name: ' + parsedSearchResponse[i].name);
                console.log('url: ' + parsedSearchResponse[i].url);
                console.log('displayUrl: ' + parsedSearchResponse[i].displayUrl); 
                console.log('snippet: ' + parsedSearchResponse[i].snippet);
                console.log('dateLastCrawled: ' + parsedSearchResponse[i].dateLastCrawled);
                console.log();
            
            }
            console.log("\n###################################");
        });

        return parsedSearchResponse;
    } 
}    

欢迎来到异步编程的精彩世界。

您的函数 return 在请求完成之前。一个片段胜过千言万语,看看发生了什么以及顺序是什么:

// 1. Start an http request and register a callback to back when complete
request(info, function(error, response, body) {
    // 3. This function is called once the request is complete
    searchResponse = JSON.parse(body);

    for (var i = 0; i < searchResponse.webPages.value.length; ++i) {
        webPage = searchResponse.webPages.value[i];
        parsedSearchResponse.push(searchResponse.webPages.value[i]);
    }

    // 4. Your array is ready but your function returned long ago
});

// 2. Return parsedSearchResponse, an empty array at this point
return parsedSearchResponse;

您需要等待您的请求完成,然后才能return执行您的功能。最好的方法是通过承诺。我通常不建议切换到新库,但由于请求已弃用并且不支持承诺,我会例外并建议您切换到另一个 http 客户端。我喜欢 axios 但任何支持 promises 的客户都可以。

这是您问题的可能解决方案,我没有测试它,因为我没有凭据,但如果有任何问题,请随时发表评论。

import { Injectable } from '@nestjs/common';
import axios from 'axios';

// Put this values in environment variable
const subscriptionKey = "SUBSCRIPTION_KEY";
const customConfigId = "CONFIG_ID";

@Injectable()
export class SearchEngineService {
  async processRequest() {
    let webPage;
    const parsedSearchResponse = [];
    const searchTerm = "partner";

    const url = `https://api.cognitive.microsoft.com/bingcustomsearch/v7.0/search?q=${searchTerm}&customconfig=${customConfigId}`

    const options = {
      headers: {
        'Ocp-Apim-Subscription-Key' : subscriptionKey
      }
    }

    try {
      const { data: searchResponse } = await axios.get(url, options);

      for (let i = 0; i < searchResponse.webPages.value.length; ++i) {
        webPage = searchResponse.webPages.value[i];
        parsedSearchResponse.push(searchResponse.webPages.value[i]);
      }
    } catch (e) {
        // Handle your error cases
    }

    return parsedSearchResponse;
  }
}