2017-02-08 3 views
0

Ich bin fast neu bei node.js, express und ES6, aber ich versuche es zu verstehen. Ich habe diesen Code geschrieben, um ordentlich saubere ES6-gesteuerte Funktionen und Versprechungen zu erreichen. Aber ich habe ein Problem mit geerbten Funktionen und Werten, vor allem next(). Also hier ist mein Code geschrieben, so weit:Versprechen immer ausstehend (falsche Syntax?)

let get_tags = (id) => { 
     var id = id; 
     return database.connection(
      (connection) => { 
       return connection.query(
        `SELECT 
         t.name 
        FROM 
         wp_terms AS t 
        INNER JOIN 
         wp_term_taxonomy AS tt ON tt.term_id = t.term_id 
        INNER JOIN 
         wp_term_relationships AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id 
        WHERE 
         tt.taxonomy IN ('post_tag') AND tr.object_id IN (${id}) 
        ORDER BY t.name ASC` 
       ) 
      } 
     ).then(
      (rows) => { 
       return rows; 
      } 
     ) 
    } 

    router.get('/:city', (req, res, next) => { 
     switch (req.params.city) { 
      case 'neanderland': 
       var post_type = 'neanderland', 
        title = 'Hauptmeldungen', 
        region = 'Neanderland'; 
       break; 
      case 'wuelfrath': 
       var post_type = 'wuelfrath', 
        title = 'Hauptmeldungen', 
        region = 'Wülfrath'; 
       break; 
      case 'mettmann': 
       var post_type = 'mettmann', 
        title = 'Hauptmeldungen', 
        region = 'Mettmann'; 
       break; 
      case 'haan': 
       var post_type = 'haan', 
        title = 'Hauptmeldungen', 
        region = 'Haan'; 
       break; 
      case 'nevigestoenisheide': 
       var post_type = 'neviges-toenisheide', 
        title = 'Hauptmeldungen', 
        region = 'Neviges/Tönisheide'; 
       break; 
     } 
     database.connection(
      (connection) => { 
       return connection.query(
        `SELECT 
          p.post_title as title, 
          p.post_author as author, 
          t.name as category, 
          p.ID as id, 
          p.post_date as date, 
          p.post_content as text, 
          p.post_excerpt as excerpt, 
          p.post_status as status, 
          p.post_name as slug_url, 
          pm1.meta_value as hero_thumb_id, 
          pm2.meta_value as hero_thumb_url 
         FROM 
          wp_posts p 
         LEFT JOIN 
          wp_postmeta pm1 
          ON (
           pm1.post_id = p.id 
           AND pm1.meta_value IS NOT NULL 
           AND pm1.meta_key = "_thumbnail_id" 
          ) 
         LEFT JOIN 
          wp_postmeta pm2 
          ON (
           pm1.meta_value = pm2.post_id 
           AND pm2.meta_key = "_wp_attached_file" 
           AND pm2.meta_value IS NOT NULL 
          ) 
         LEFT JOIN 
          wp_term_relationships tr 
          ON (
           p.ID = tr.object_id 
          ) 
         LEFT JOIN 
          wp_term_taxonomy tt 
          ON (
           tr.term_taxonomy_id = tt.term_taxonomy_id 
          ) 
         LEFT JOIN 
          wp_terms t 
          ON (
           tt.term_id = t.term_id 
          ) 
         WHERE 
          p.post_status="publish" 
          AND p.post_type="${post_type}" 
          AND tt.taxonomy = "category" 
         GROUP BY p.ID 
         ORDER BY 
          p.post_date DESC 
         LIMIT 100` 
       ) 
      } 
     ).then(
      (rows) => { 
       var posts = []; 
       rows.forEach(
        (element, index, array) => { 
         var arr = { 
          id : element.id, 
          paywall : element.text.includes('[not-level-free-user]'), 
          date : Date.parse(element.date).format("c"), 
          title : element.title, 
          excerpt : element.excerpt, 
          text : convert_text(element.text), 
          category : convert_category(element.category), 
          region : region, 
          author : convert_author(element.author), 
          slug : element.slug_url, 
          tags : '', 
          media : { 
           heroid : element.hero_thumb_id, 
           heroslug: element.hero_thumb_url 
          } 
         } 
         posts.push(arr); 
        } 
       ); 
       return posts; 
      } 
     ).then(
      (data) => { 
       var arr = []; 
       data.forEach(
        (element, index, array) => { 
         var id = element.id; 
         var item = get_tags(id).then(
          (result) => { 
           if (result.length >= 1) { 
            // console.log(result) at this position returns e.g. 
            // [ RowDataPacket { name: 'Feuerwehr' }, 
            // RowDataPacket { name: 'Nachwuchs' }, 
            // RowDataPacket { name: 'Werbung' } ] 
            return result; 
           } 
          } 
         ) 
         // console.log(item) at this position returns 
         // Promise { <pending> } 
         arr.push(item); 
        } 
       ); 
       return arr; 
      } 
     ).then(
      (data) => { 
       res.json(data) 
      } 
     ); 

    }); 

Alles funktioniert gut, bis zum vorletzten dann(). Es gibt nur leere Elemente eines Arrays zurück. Es scheint, dass get_tags (id) die Ergebnisse für die nächste nicht speichert. Ich habe ein Konsolenprotokoll an bestimmten Positionen erstellt, aber ich kann den Fehler nicht finden ... Ich möchte die Ergebnisse von get_tags in die arr-Variable speichern, um sie für die folgende next() - Funktion zurückzugeben. Sie können die Ergebnisse in den Kommentaren finden.

Hat jemand eine Idee, was könnte schief gehen?

Danke für die Hilfe und bitte sei nett ... Ich bin immer noch ein Anfänger! ;-)

+3

Können Sie den Beispielcode minimieren prägnanter um das Problem zu veranschaulichen?Ich glaube nicht, dass wir zwei Bildschirme von SQL-Abfragen sehen müssen ... – deceze

Antwort

2

Das Problem ist im then Rückruf, der get_tags aufruft. Da es sich bei get_tabs um einen asynchronen Aufruf handelt, müssen Sie darauf warten, dass diese Versprechungen abgeschlossen werden. Dies ist problemlos mit Promise.all möglich.

Der Versuch, hier zu Ihrem Stil zu halten:

// ... 
).then(
    (data) => { 
     // Map the data to promises and return a promise that waits for them 
     return Promise.all(data.map(
      (element, index, array) => { 
       var id = element.id; 
       return get_tags(id); 
      } 
     )); 
    } 
// Now we use a new `then` to filter the data now we have it 
).then(
    (data) => { 
     return data.filter(
      (result) => { 
       return result.length > 1; 
      } 
     ); 
    } 
) 
// ... 

Randbemerkung: Diese then früher dient auf keinen Zweck:

).then(
    (rows) => { 
     return rows; 
    } 
) 

es kann nur vollständig entfernt werden (ersetzt mit nur dass ) am Ende). .

Ein paar andere v kleinere Anmerkungen:

  • Sie brauchen nicht () um den Parameter auf einen Pfeil Funktion, wenn es nur einen Parameter ist (obwohl natürlich können Sie Konsistenz als eine Angelegenheit von bevorzugen Stil)
  • Die prägnante Form der Pfeilfunktionen ist häufig nützlich (wie das Beispiel, das ich oben gezeigt habe, das Filtern der Ergebnisse durch result.length > 1).

Hier ist, wie ich am Anfang der Antwort den Block schreiben würde, FWIW:

// ... 
) 
.then(data => Promise.all(data.map(entry => get_tags(entry.id)))) 
.then(data => data.filter(result => result.length > 1)) 
// ... 

... aber es ist eine Frage des Stils, und in gewissem Maße auch davon ab, was Debugger Sie neigen dazu, zu verwenden, da einige besser sind, einzelne Linien wie das als andere zu behandeln.

+1

Vor allem: Vielen Dank für Ihre Zeit und alle Vorschläge. Es hilft mir, besser zu werden und zu lernen, wie die Arbeit funktioniert. Ich werde den Code implementieren und sehen, wie es läuft. Daumen hoch!!! –

0

Also habe ich Ihren Code implementiert, es funktioniert natürlich. Aber irgendwie habe ich es nicht geschafft, deinen Code mit meiner Array-Injektion zu integrieren. Dies ist mein Ergebnis, um das Array mit den Tags im tag-Element zu füllen. Vielleicht haben Sie eine bessere und kürzere Lösung?

.then(
    (data) => { 
     var test = data; 
     return Promise.all(
      data.map(
       (element, index, array) => { 
        var id = element.id; 
        return get_tags(id); 
       } 
      ) 
     ).then(
      data => { 
       data.forEach(
        (element, index, array) => { 
         var tag = []; 
         element.forEach(
          (element, index, array) => { 
           tag.push(element.name); 
          } 
         ); 
         test[index].tags = tag; 
        } 
       ); 
       return test; 
      } 
     ); 
    } 
) 

Mein gewünschtes Ergebnis (mit Fokus auf dem „Tags“):

{ 
    "id": 123456, 
    "paywall": true, 
    "date": "2017-01-24T15:02:38.000Z", 
    "title": "This is a headline", 
    "excerpt": "This is an excerpt", 
    "text": "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.", 
    "category": "main", 
    "region": "city", 
    "author": "John Johnson", 
    "slug": "this-is-a-headline", 
    "tags": [ 
     "Tag1", 
     "Tag2", 
     "Tag3" 
    ], 
    "media": { 
     "heroid": "123456", 
     "heroslug": "2017/02/heroimage.jpg" 
    } 
}