Esercitazione: Creare un'app a singola pagina con l'API Ricerca Web BingTutorial: Create a single-page app using the Bing Web Search API

Questa app di una pagina offre una dimostrazione su come recuperare, analizzare e visualizzare i risultati della ricerca dall'API Ricerca Web Bing.This single-page app demonstrates how to retrieve, parse, and display search results from the Bing Web Search API. L'esercitazione usa codice HTML e CSS boilerplate ed è incentrata sul codice JavaScript.The tutorial uses boilerplate HTML and CSS, and focuses on the JavaScript code. I file HTML, CSS e JS sono disponibili su GitHub insieme a istruzioni di avvio rapido.HTML, CSS, and JS files are available on GitHub with quickstart instructions.

Questa app di esempio può:This sample app can:

  • Chiamare l'API Ricerca Web Bing con le opzioni di ricercaCall the Bing Web Search API with search options
  • Visualizzare risultati su contenuti Web, immagini, notizie e videoDisplay web, image, news, and video results
  • Impaginare i risultatiPaginate results
  • Gestire le chiavi di sottoscrizioneManage subscription keys
  • Gestire gli erroriHandle errors

Per usare questa app è necessario un account di Servizi cognitivi di Azure con le API di ricerca Bing.To use this app, an Azure Cognitive Services account with Bing Search APIs is required. Se non si dispone di un account, è possibile usare la versione di valutazione gratuita per ottenere una chiave di sottoscrizione.If you don't have an account, you can use the free trial to get a subscription key.

PrerequisitiPrerequisites

Per eseguire l'app occorre:Here are a few things that you'll need to run the app:

  • Node.js 8 o versione successivaNode.js 8 or later
  • Una chiave di sottoscrizioneA subscription key

Ottenere il codice sorgente e installare le dipendenzeGet the source code and install dependencies

Il primo passaggio consiste nel clonare il repository con il codice sorgente dell'app.The first step is to clone the repository with the sample app's source code.

git clone https://github.com/Azure-Samples/cognitive-services-REST-api-samples.git

Quindi eseguire npm install.Then run npm install. Per questa esercitazione, Express.js è l'unica dipendenza.For this tutorial, Express.js is the only dependency.

cd <path-to-repo>/cognitive-services-REST-api-samples/Tutorials/Bing-Web-Search
npm install

Componenti dell'appApp components

L'app di esempio che si sta creando è costituita da quattro parti:The sample app we're building is made up of four parts:

  • bing-web-search.js: l'app Express.js.bing-web-search.js - Our Express.js app. Gestisce la logica di richiesta/risposta e il routing.It handles request/response logic and routing.
  • public/index.html: lo scheletro dell'app. Definisce il modo in cui i dati vengono presentati all'utente.public/index.html - The skeleton of our app; it defines how data is presented to the user.
  • public/css/styles.css: definisce gli stili di pagina, come i tipi di carattere, i colori e le dimensioni del testo.public/css/styles.css - Defines page styles, such as fonts, colors, text size.
  • public/js/scripts.js: contiene la logica per inviare richieste all'API Ricerca Web Bing, gestire le chiavi di sottoscrizione, gestire e analizzare le risposte e visualizzare i risultati.public/js/scripts.js - Contains the logic to make requests to the Bing Web Search API, manage subscription keys, handle and parse responses, and display results.

Questa esercitazione è incentrata su scripts.js e sulla logica necessaria per chiamare l'API Ricerca Web Bing e gestire la risposta.This tutorial focuses on scripts.js and the logic required to call the Bing Web Search API and handle the response.

Form HTMLHTML form

index.html include un modulo che consente agli utenti di cercare e selezionare opzioni di ricerca.The index.html includes a form that enables users to search and select search options. L'attributo onsubmit viene attivato all'invio del modulo, chiamando il metodo bingWebSearch() definito in scripts.js.The onsubmit attribute fires when the form is submitted, calling the bingWebSearch() method defined in scripts.js. Accetta tre argomenti:It takes three arguments:

  • Query di ricercaSearch query
  • Opzioni selezionateSelected options
  • Chiave della sottoscrizioneSubscription key
<form name="bing" onsubmit="return bingWebSearch(this.query.value,
    bingSearchOptions(this), getSubscriptionKey())">

Opzioni di queryQuery options

Il modulo HTML include opzioni che eseguono il mapping ai parametri di query nell'API Ricerca Web Bing v7.The HTML form includes options that map to query parameters in the Bing Web Search API v7. La tabella seguente mostra in che modo gli utenti possono filtrare i risultati della ricerca usando l'app di esempio:This table provides a breakdown of how users can filter search results using the sample app:

ParametroParameter DESCRIZIONEDescription
query Campo di testo in cui immettere una stringa di query.A text field to enter a query string.
where Menu a discesa in cui selezionare il mercato (località e lingua).A drop-down menu to select the market (location and language).
what Caselle di controllo per alzare di livello tipi di risultati specifici.Checkboxes to promote specific result types. Alzando di livello le immagini, ad esempio, se ne alza la classificazione nei risultati della ricerca.Promoting images, for example, increases the ranking of images in search results.
when Menu a discesa che consente all'utente di limitare i risultati della ricerca alla data odierna, alla settimana corrente o al mese corrente.A drop-down menu that allows the user to limit the search results to today, this week, or this month.
safe Casella di controllo che consente di abilitare Ricerca sicura Bing, che esclude i contenuti per adulti.A checkbox to enable Bing SafeSearch, which filters out adult content.
count Campo nascosto.Hidden field. Il numero di risultati della ricerca da restituire per ogni richiesta.The number of search results to return on each request. Modificare questo valore per visualizzare un numero maggiore o minore di risultati per pagina.Change this value to display fewer or more results per page.
offset Campo nascosto.Hidden field. Lo scostamento del primo risultato della ricerca nella richiesta, che viene usato per l'impaginazione.The offset of the first search result in the request, which is used for paging. Viene reimpostato su 0 con ogni nuova richiesta.It's reset to 0 with each new request.

Nota

L'API Ricerca Web Bing offre altri parametri di query per affinare i risultati della ricerca.The Bing Web Search API offers additional query parameters to help refine search results. Questo esempio ne usa solo alcuni.This sample only uses a few. Per un elenco completo dei parametri disponibili, vedere Informazioni di riferimento per l'API Ricerca Web Bing v7.For a complete list of available parameters, see Bing Web Search API v7 reference.

La funzione bingSearchOptions() converte queste opzioni nel formato richiesto dall'API di ricerca Bing.The bingSearchOptions() function converts these options to match the format required by the Bing Search API.

// Build query options from selections in the HTML form.
function bingSearchOptions(form) {

    var options = [];
    // Where option.
    options.push("mkt=" + form.where.value);
    // SafeSearch option.
    options.push("SafeSearch=" + (form.safe.checked ? "strict" : "off"));
    // Freshness option.
    if (form.when.value.length) options.push("freshness=" + form.when.value);
    var what = [];
    for (var i = 0; i < form.what.length; i++)
        if (form.what[i].checked) what.push(form.what[i].value);
    // Promote option.
    if (what.length) {
        options.push("promote=" + what.join(","));
        options.push("answerCount=9");
    }
    // Count option.
    options.push("count=" + form.count.value);
    // Offset option.
    options.push("offset=" + form.offset.value);
    // Hardcoded text decoration option.
    options.push("textDecorations=true");
    // Hardcoded text format option.
    options.push("textFormat=HTML");
    return options.join("&");
}

SafeSearchpuò essere impostato su strict, moderate o off. moderate è l'impostazione predefinita per Ricerca Web Bing.SafeSearch can be set to strict, moderate, or off, with moderate being the default setting for Bing Web Search. Questo modulo usa una casella di controllo che presenta due stati.This form uses a checkbox, which has two states. In questo frammento di codice Ricerca sicura è impostata su strict o off. moderate non viene usato.In this snippet, SafeSearch is set to strict or off, moderate isn't used.

Se una qualsiasi delle caselle di controllo Alza di livello è selezionata, il parametro answerCount viene aggiunto alla query.If any of the Promote checkboxes are selected, the answerCount parameter is added to the query. answerCount è necessario quando si usa il parametro promote.answerCount is required when using the promote parameter. In questo frammento di codice il valore è impostato su 9 per restituire tutti i tipi di risultati disponibili.In this snippet, the value is set to 9 to return all available result types.

Nota

L'innalzamento di livello di un tipo di risultato non garantisce che verrà incluso nei risultati della ricerca.Promoting a result type doesn't guarantee that it will be included in the search results. ma si alza la classificazione di questi tipi di risultati rispetto alla loro classificazione consueta.Rather, promotion increases the ranking of those kinds of results relative to their usual ranking. Per limitare le ricerche a determinati tipi di risultati, usare il parametro di query responseFilter o chiamare un endpoint più specifico, ad esempio Ricerca immagini Bing o Ricerca notizie Bing.To limit searches to particular kinds of results, use the responseFilter query parameter, or call a more specific endpoint such as Bing Image Search or Bing News Search.

I parametri di query textDecoration e textFormat sono hardcoded nello script e fanno in modo che il termine di ricerca appaia in grassetto nei risultati della ricerca.The textDecoration and textFormat query parameters are hardcoded into the script, and cause the search term to be boldfaced in the search results. Questi parametri non sono obbligatori.These parameters aren't required.

Gestire le chiavi di sottoscrizioneManage subscription keys

Per evitare l'hardcoding della chiave di sottoscrizione dell'API di ricerca Bing, questa app di esempio usa l'archiviazione permanente del browser per archiviare la chiave.To avoid hardcoding the Bing Search API subscription key, this sample app uses a browser's persistent storage to store the subscription key. Se non è archiviata alcuna chiave di sottoscrizione, all'utente viene chiesto di immetterne una.If no subscription key is stored, the user is prompted to enter one. Se la chiave di sottoscrizione viene rifiutata dall'API, all'utente viene chiesto di reimmetterne una.If the subscription key is rejected by the API, the user is prompted to re-enter a subscription key.

La funzione getSubscriptionKey() usa le funzioni storeValue e retrieveValue per archiviare e recuperare la chiave di sottoscrizione di un utente.The getSubscriptionKey() function uses the storeValue and retrieveValue functions to store and retrieve a user's subscription key. Queste funzioni usano l'oggetto localStorage, se supportato, oppure i cookie.These functions use the localStorage object, if supported, or cookies.

// Cookie names for stored data.
API_KEY_COOKIE   = "bing-search-api-key";
CLIENT_ID_COOKIE = "bing-search-client-id";

BING_ENDPOINT = "https://api.cognitive.microsoft.com/bing/v7.0/search";

// See source code for storeValue and retrieveValue definitions.

// Get stored subscription key, or prompt if it isn't found.
function getSubscriptionKey() {
    var key = retrieveValue(API_KEY_COOKIE);
    while (key.length !== 32) {
        key = prompt("Enter Bing Search API subscription key:", "").trim();
    }
    // Always set the cookie in order to update the expiration date.
    storeValue(API_KEY_COOKIE, key);
    return key;
}

Come abbiamo visto in precedenza, all'invio del modulo viene attivato onsubmit, che chiama bingWebSearch.As we saw earlier, when the form is submitted, onsubmit fires, calling bingWebSearch. Questa funzione inizializza e invia la richiesta.This function initializes and sends the request. getSubscriptionKey viene chiamato a ogni invio per autenticare la richiesta.getSubscriptionKey is called on each submission to authenticate the request.

Dati la query, la stringa delle opzioni e la chiave di sottoscrizione, la funzione BingWebSearch crea un oggetto XMLHttpRequest per chiamare l'endpoint di Ricerca Web Bing.Given the query, the options string, and the subscription key, the BingWebSearch function creates an XMLHttpRequest object to call the Bing Web Search endpoint.

// Perform a search constructed from the query, options, and subscription key.
function bingWebSearch(query, options, key) {
    window.scrollTo(0, 0);
    if (!query.trim().length) return false;

    showDiv("noresults", "Working. Please wait.");
    hideDivs("pole", "mainline", "sidebar", "_json", "_http", "paging1", "paging2", "error");

    var request = new XMLHttpRequest();
    var queryurl = BING_ENDPOINT + "?q=" + encodeURIComponent(query) + "&" + options;

    // Initialize the request.
    try {
        request.open("GET", queryurl);
    }
    catch (e) {
        renderErrorMessage("Bad request (invalid URL)\n" + queryurl);
        return false;
    }

    // Add request headers.
    request.setRequestHeader("Ocp-Apim-Subscription-Key", key);
    request.setRequestHeader("Accept", "application/json");
    var clientid = retrieveValue(CLIENT_ID_COOKIE);
    if (clientid) request.setRequestHeader("X-MSEdge-ClientID", clientid);

    // Event handler for successful response.
    request.addEventListener("load", handleBingResponse);

    // Event handler for errors.
    request.addEventListener("error", function() {
        renderErrorMessage("Error completing request");
    });

    // Event handler for an aborted request.
    request.addEventListener("abort", function() {
        renderErrorMessage("Request aborted");
    });

    // Send the request.
    request.send();
    return false;
}

Se la richiesta riesce, viene attivato il gestore dell'evento load che chiama la funzione handleBingResponse.Following a successful request, the load event handler fires and calls the handleBingResponse function. handleBingResponse analizza l'oggetto risultato, visualizza i risultati e contiene la logica di errore per le richieste non riuscite.handleBingResponse parses the result object, displays the results, and contains error logic for failed requests.

function handleBingResponse() {
    hideDivs("noresults");

    var json = this.responseText.trim();
    var jsobj = {};

    // Try to parse results object.
    try {
        if (json.length) jsobj = JSON.parse(json);
    } catch(e) {
        renderErrorMessage("Invalid JSON response");
        return;
    }

    // Show raw JSON and the HTTP request.
    showDiv("json", preFormat(JSON.stringify(jsobj, null, 2)));
    showDiv("http", preFormat("GET " + this.responseURL + "\n\nStatus: " + this.status + " " +
        this.statusText + "\n" + this.getAllResponseHeaders()));

    // If the HTTP response is 200 OK, try to render the results.
    if (this.status === 200) {
        var clientid = this.getResponseHeader("X-MSEdge-ClientID");
        if (clientid) retrieveValue(CLIENT_ID_COOKIE, clientid);
        if (json.length) {
            if (jsobj._type === "SearchResponse" && "rankingResponse" in jsobj) {
                renderSearchResults(jsobj);
            } else {
                renderErrorMessage("No search results in JSON response");
            }
        } else {
            renderErrorMessage("Empty response (are you sending too many requests too quickly?)");
        }
    }

    // Any other HTTP response is considered an error.
    else {
        // 401 is unauthorized; force a re-prompt for the user's subscription
        // key on the next request.
        if (this.status === 401) invalidateSubscriptionKey();

        // Some error responses don't have a top-level errors object, if absent
        // create one.
        var errors = jsobj.errors || [jsobj];
        var errmsg = [];

        // Display the HTTP status code.
        errmsg.push("HTTP Status " + this.status + " " + this.statusText + "\n");

        // Add all fields from all error responses.
        for (var i = 0; i < errors.length; i++) {
            if (i) errmsg.push("\n");
            for (var k in errors[i]) errmsg.push(k + ": " + errors[i][k]);
        }

        // Display Bing Trace ID if it isn't blocked by CORS.
        var traceid = this.getResponseHeader("BingAPIs-TraceId");
        if (traceid) errmsg.push("\nTrace ID " + traceid);

        // Display the error message.
        renderErrorMessage(errmsg.join("\n"));
    }
}

Importante

Una richiesta HTTP corretta non indica necessariamente che la ricerca sia riuscita.A successful HTTP request doesn't mean that the search itself succeeded. Se si verifica un errore nell'operazione di ricerca, l'API Ricerca Web Bing restituisce un codice di stato HTTP non-200 e include le informazioni sull'errore nella risposta JSON.If an error occurs in the search operation, the Bing Web Search API returns a non-200 HTTP status code and includes error information in the JSON response. Se la richiesta era a frequenza limitata, l'API restituisce una risposta vuota.If the request was rate-limited, the API returns an empty response.

La maggior parte del codice in entrambe le funzioni precedenti è dedicata alla gestione degli errori.Much of the code in both of the preceding functions is dedicated to error handling. Possono verificarsi errori nelle fasi seguenti:Errors may occur at the following stages:

FaseStage Errori potenzialiPotential error(s) Gestiti daHandled by
Compilazione dell'oggetto della richiestaBuilding the request object URL non validoInvalid URL Blocco try / catchtry / catch block
Invio della richiestaMaking the request Errori di rete, connessioni interrotteNetwork errors, aborted connections Gestori degli eventi error e aborterror and abort event handlers
Esecuzione della ricercaPerforming the search Richiesta non valida, JSON non valido, limiti di frequenzaInvalid request, invalid JSON, rate limits Test nel gestore dell'evento loadTests in load event handler

Gli errori vengono gestiti chiamando renderErrorMessage().Errors are handled by calling renderErrorMessage(). Se la risposta supera tutti i test di errore, viene chiamato renderSearchResults() per visualizzare i risultati della ricerca.If the response passes all of the error tests, renderSearchResults() is called to display the search results.

Visualizzare i risultati della ricercaDisplay search results

I risultati restituiti dall'API Ricerca Web Bing sono soggetti a requisiti di utilizzo e visualizzazione.There are use and display requirements for results returned by the Bing Web Search API. Poiché una risposta può includere vari tipi di risultati, non è sufficiente scorrere la raccolta WebPages di primo livello.Since a response may include various result types, it isn't enough to iterate through the top-level WebPages collection. L'app di esempio usa invece RankingResponse per ordinare i risultati secondo un criterio specifico.Instead, the sample app uses RankingResponse to order the results to spec.

Nota

Se si vuole visualizzare un solo tipo di risultato, usare il parametro di query responseFilter oppure provare a usare uno degli altri endpoint di Ricerca Bing, come Ricerca immagini Bing.If you only want a single result type, use the responseFilter query parameter, or consider using one of the other Bing Search endpoints, such as Bing Image Search.

Ogni risposta ha un oggetto RankingResponse che può includere fino a tre raccolte: pole, mainline e sidebar.Each response has a RankingResponse object that may include up to three collections: pole, mainline, and sidebar. pole, se presente, è il risultato della ricerca più pertinente e deve essere visualizzato in primo piano.pole, if present, is the most relevant search result and must be prominently displayed. mainline contiene la maggior parte dei risultati della ricerca e viene visualizzato immediatamente dopo pole.mainline contains most of the search results, and is displayed immediately after pole. sidebar include risultati della ricerca ausiliari.sidebar includes auxiliary search results. Se possibile, questi risultati devono essere visualizzati nella barra laterale.If possible, these results should be displayed in the sidebar. Se i limiti dello schermo non consentono di mostrare una barra laterale, devono essere visualizzati dopo i risultati mainline.If screen limits make a sidebar impractical, these results should appear after the mainline results.

Ogni RankingResponse include una matrice di RankingItem che specifica come devono essere ordinati i risultati.Each RankingResponse includes a RankingItem array that specifies how results must be ordered. L'app di esempio usa i parametri answerType e resultIndex per identificare il risultato.Our sample app uses the answerType and resultIndex parameters to identify the result.

Nota

È possibile identificare e classificare i risultati anche in altri modi.There are additional ways to identify and rank results. Per altre informazioni, vedere Uso della classificazione per visualizzare i risultati.For more information, see Using ranking to display results.

Esaminiamo il codice:Let's take a look at the code:

// Render the search results from the JSON response.
function renderSearchResults(results) {

    // If spelling was corrected, update the search field.
    if (results.queryContext.alteredQuery)
        document.forms.bing.query.value = results.queryContext.alteredQuery;

    // Add Prev / Next links with result count.
    var pagingLinks = renderPagingLinks(results);
    showDiv("paging1", pagingLinks);
    showDiv("paging2", pagingLinks);

    // Render the results for each section.
    for (section in {pole: 0, mainline: 0, sidebar: 0}) {
        if (results.rankingResponse[section])
            showDiv(section, renderResultsItems(section, results));
    }
}

La funzione renderResultsItems() scorre gli elementi in ogni raccolta RankingResponse, esegue il mapping di ogni risultato della classificazione a un risultato della ricerca mediante i valori answerType e resultIndex e chiama la funzione di rendering appropriata per generare l'HTML.The renderResultsItems() function iterates through the items in each RankingResponse collection, maps each ranking result to a search result using the answerType and resultIndex values, and calls the appropriate rendering function to generate the HTML. Se resultIndex non viene specificato per un elemento, renderResultsItems() scorre tutti i risultati di quel tipo e chiama la funzione di rendering per ogni elemento.If resultIndex isn't specified for an item, renderResultsItems() iterates through all results of that type and calls the rendering function for each item. Il codice HTML risultante viene inserito nell'elemento <div> appropriato in index.html.The resulting HTML is inserted into the appropriate <div> element in index.html.

// Render search results from the RankingResponse object per rank response and
// use and display requirements.
function renderResultsItems(section, results) {

    var items = results.rankingResponse[section].items;
    var html = [];
    for (var i = 0; i < items.length; i++) {
        var item = items[i];
        // Collection name has lowercase first letter while answerType has uppercase
        // e.g. `WebPages` RankingResult type is in the `webPages` top-level collection.
        var type = item.answerType[0].toLowerCase() + item.answerType.slice(1);
        if (type in results && type in searchItemRenderers) {
            var render = searchItemRenderers[type];
            // This ranking item refers to ONE result of the specified type.
            if ("resultIndex" in item) {
                html.push(render(results[type].value[item.resultIndex], section));
            // This ranking item refers to ALL results of the specified type.
            } else {
                var len = results[type].value.length;
                for (var j = 0; j < len; j++) {
                    html.push(render(results[type].value[j], section, j, len));
                }
            }
        }
    }
    return html.join("\n\n");
}

Esaminare le funzioni rendererReview renderer functions

Nell'app di esempio l'oggetto searchItemRenderers include funzioni che generano codice HTML per ogni tipo di risultato della ricerca.In our sample app, the searchItemRenderers object includes functions that generate HTML for each type of search result.

// Render functions for each result type.
searchItemRenderers = {
    webPages: function(item) { ... },
    news: function(item) { ... },
    images: function(item, section, index, count) { ... },
    videos: function(item, section, index, count) { ... },
    relatedSearches: function(item, section, index, count) { ... }
}

Importante

L'app include renderer per pagine Web, notizie, immagini, video e ricerche correlate.The sample app has renderers for web pages, news, images, videos, and related searches. Un'applicazione deve avere renderer per tutti i tipi di risultati che può ricevere, fra cui possono essere inclusi calcoli, suggerimenti di ortografia, entità, fusi orari e definizioni.Your application will need renderers for any type of results it may receive, which could include computations, spelling suggestions, entities, time zones, and definitions.

Alcune delle funzioni di rendering accettano solo il parametro item.Some of the rendering functions accept only the item parameter. Altre accettano parametri aggiuntivi, che possono essere usati per eseguire il rendering degli elementi in modo diverso in base al contesto.Others accept additional parameters, which can be used to render items differently based on context. Un renderer che non usa queste informazioni non ha bisogno di accettare questi parametri.A renderer that doesn't use this information doesn't need to accept these parameters.

Gli argomenti di contesto sono:The context arguments are:

ParametroParameter DESCRIZIONEDescription
section La sezione relativa ai risultati, ovvero pole, mainline o sidebar, in cui l'elemento compare.The results section (pole, mainline, or sidebar) in which the item appears.
index
count
Disponibile quando l'elemento RankingResponse specifica che tutti i risultati di una determinata raccolta devono essere visualizzati; undefined in caso contrario.Available when the RankingResponse item specifies that all results in a given collection are to be displayed; undefined otherwise. L'indice dell'elemento all'interno della raccolta e il numero totale di elementi della raccolta.The index of the item within its collection and the total number of items in that collection. È possibile usare queste informazioni per numerare i risultati, per generare codice HTML diverso per il primo o l'ultimo risultato e così via.You can use this information to number the results, to generate different HTML for the first or last result, and so on.

Nell'app di esempio entrambi i renderer images e relatedSearches usano gli argomenti di contesto per personalizzare il codice HTML generato.In the sample app, both the images and relatedSearches renderers use the context arguments to customize the generated HTML. Analizziamo in dettaglio il renderer images:Let's take a closer look at the images renderer:

searchItemRenderers = {
    // Render image result with thumbnail.
    images: function(item, section, index, count) {
        var height = 60;
        var width = Math.round(height * item.thumbnail.width / item.thumbnail.height);
        var html = [];
        if (section === "sidebar") {
            if (index) html.push("<br>");
        } else {
            if (!index) html.push("<p class='images'>");
        }
        html.push("<a href='" + item.hostPageUrl + "'>");
        var title = escape(item.name) + "\n" + getHost(item.hostPageDisplayUrl);
        html.push("<img src='"+ item.thumbnailUrl + "&h=" + height + "&w=" + width +
            "' height=" + height + " width=" + width + " title='" + title + "' alt='" + title + "'>");
        html.push("</a>");
        return html.join("");
    },
    // Other renderers are omitted from this sample...
}

Il renderer dell'immagine:The image renderer:

  • Calcola le dimensioni dell'anteprima immagine; la larghezza varia, mentre l'altezza è fissa a 60 pixel.Calculates the image thumbnail size (width varies, while height is fixed at 60 pixels).
  • Inserisce il codice HTML che precede l'immagine ottenuta come risultato in base al contesto.Inserts the HTML that precedes the image result based on context.
  • Compila il tag HTML <a> per il collegamento alla pagina contenente l'immagine.Builds the HTML <a> tag that links to the page that contains the image.
  • Compila il tag HTML <img> per visualizzare l'anteprima dell'immagine.Builds the HTML <img> tag to display the image thumbnail.

Usa il renderer di immagini per le variabili section e index per visualizzare i risultati in modo diverso a seconda di dove vengono mostrati.The image renderer uses the section and index variables to display results differently depending on where they appear. Un'interruzione di riga, tag <br>, viene inserita tra le immagini ottenute come risultato nella barra laterale, in modo che la barra laterale mostri una colonna di immagini.A line break (<br> tag) is inserted between image results in the sidebar, so that the sidebar displays a column of images. In altre sezioni la prima immagine dei risultati (index === 0) è preceduta da un tag <p>.In other sections, the first image result (index === 0) is preceded by a <p> tag.

La dimensione dell'anteprima viene usata sia nel tag <img> che nei campi h e w dell'URL dell'anteprima.The thumbnail size is used in both the <img> tag and the h and w fields in the thumbnail's URL. Gli attributi title e alt, una descrizione testuale dell'immagine, sono costruiti dal nome dell'immagine e il nome host nell'URL.The title and alt attributes (a textual description of the image) are constructed from the image's name and the hostname in the URL.

Ecco un esempio del modo in cui vengono visualizzate le immagini nell'app di esempio:Here's an example of how images are displayed in the sample app:

[Immagine ottenute come risultato da Bing]

Salvare l'ID client in modo permanentePersist the client ID

Le risposte dalle API di ricerca Bing potrebbero includere un'intestazione X-MSEdge-ClientID che deve essere reinviata all'API con ogni richiesta successiva.Responses from the Bing search APIs may include a X-MSEdge-ClientID header that should be sent back to the API with each successive request. Se l'app usa più di un'API di ricerca Bing, assicurarsi che venga inviato lo stesso ID client con ogni richiesta ai vari servizi.If more than one of the Bing Search APIs is used by your app, make sure the same client ID is sent with each request across services.

Fornire l'intestazione X-MSEdge-ClientID consente alle API Bing di associare le ricerche di un utente.Providing the X-MSEdge-ClientID header allows the Bing APIs to associate a user's searches. In questo modo consente al motore di ricerca Bing di applicare un contesto passato alle ricerche per trovare i risultati che meglio soddisfano la richiesta.First, it allows the Bing search engine to apply past context to searches to find results that better satisfy the request. Se un utente ha cercato in precedenza termini correlati alla navigazione, ad esempio, una successiva ricerca di "nodi" potrebbe restituire preferibilmente informazioni sui nodi utilizzati nella navigazione.If a user has previously searched for terms related to sailing, for example, a later search for "knots" might preferentially return information about knots used in sailing. In secondo luogo, Bing potrebbe selezionare utenti in modo casuale per provare nuove funzionalità prima di renderle disponibili.Second, Bing may randomly select users to experience new features before they are made widely available. Fornire lo stesso ID client per tutte le richieste fa sì che gli utenti selezionati per la visualizzazione di una funzionalità la visualizzino sempre.Providing the same client ID with each request ensures that users who have been chosen to see a feature will always see it. Senza un ID client, l'utente potrebbe vedere una funzionalità apparire e scomparire apparentemente in modo casuale nei risultati delle ricerche.Without the client ID, the user might see a feature appear and disappear, seemingly at random, in their search results.

I criteri di sicurezza del browser, come Condivisione risorse tra le origini (CORS), potrebbero impedire all'app di esempio di accedere all'intestazione X-MSEdge-ClientID.Browser security policies, such as Cross-Origin Resource Sharing (CORS), may prevent the sample app from accessing the X-MSEdge-ClientID header. Questa limitazione si verifica quando la risposta della ricerca ha un'origine diversa dalla pagina che l'ha richiesta.This limitation occurs when the search response has a different origin from the page that requested it. In un ambiente di produzione è necessario soddisfare questo criterio tramite l'hosting di uno script sul lato server che esegue la chiamata API nello stesso dominio della pagina Web.In a production environment, you should address this policy by hosting a server-side script that does the API call on the same domain as the Web page. Poiché lo script ha la stessa origine della pagina Web, l'intestazione X-MSEdge-ClientID diventa disponibile per JavaScript.Since the script has the same origin as the Web page, the X-MSEdge-ClientID header is then available to JavaScript.

Nota

In un'applicazione Web di produzione è consigliabile comunque eseguire la richiesta lato server.In a production Web application, you should perform the request server-side anyway. In caso contrario, la chiave di sottoscrizione dell'API di ricerca Bing deve essere inclusa nella pagina Web, dove è disponibile per chiunque visualizzi l'origine.Otherwise, your Bing Search API subscription key must be included in the web page, where it's available to anyone who views source. All'utente vengono addebitati costi per tutto l'utilizzo della chiave di sottoscrizione API, anche le richieste effettuate da parti non autorizzate, pertanto è importante che la chiave non sia visibile.You are billed for all usage under your API subscription key, even requests made by unauthorized parties, so it is important not to expose your key.

Ai fini dello sviluppo, è possibile effettuare una richiesta tramite un proxy CORS.For development purposes, you can make a request through a CORS proxy. La risposta da questo tipo di proxy ha un'intestazione Access-Control-Expose-Headers che inserisce le intestazioni di risposta in un elenco elementi consentiti e le rende disponibili a JavaScript.The response from this type of proxy has an Access-Control-Expose-Headers header that whitelists response headers and makes them available to JavaScript.

È facile installare un proxy CORS per consentire all'app di esempio di accedere all'intestazione ID client.It's easy to install a CORS proxy to allow our sample app to access the client ID header. Eseguire questo comando:Run this command:

npm install -g cors-proxy-server

Poi modificare l'endpoint di Ricerca Web Bing nel file script.js in:Next, change the Bing Web Search endpoint in script.js to:

http://localhost:9090/https://api.cognitive.microsoft.com/bing/v7.0/search

Avviare il proxy CORS con questo comando:Start the CORS proxy with this command:

cors-proxy-server

Lasciare aperta la finestra di comando mentre si usa l'app di esempio. La chiusura della finestra determina infatti l'arresto del proxy.Leave the command window open while you use the sample app; closing the window stops the proxy. Nella sezione espandibile Intestazioni HTTP sotto i risultati della ricerca dovrebbe essere visibile l'intestazione X-MSEdge-ClientID.In the expandable HTTP Headers section below the search results, the X-MSEdge-ClientID header should be visible. Verificare che sia la stessa per ogni richiesta.Verify that it's the same for each request.

Passaggi successiviNext steps