Попытка получить метаданные URL в Express / NodeJS - PullRequest
0 голосов
/ 10 апреля 2019

У меня есть ресурс, который содержит поле URL, введенное пользователем. Я пытаюсь использовать этот пакет: https://github.com/mozilla/page-metadata-parser, чтобы получить заголовок и описание, связанные с URL, и сохранить его в БД при создании.

Я добавил код, смоделированный в документации пакета, к запросу на публикацию в Express, и ошибок нет, новая закладка создана, но значения метаданных не возвращаются.

Вот моя модель:

const mongoose = require('mongoose');

const { Schema } = mongoose;

const BookmarksSchema = new Schema({
  userId: {
    type: Schema.Types.ObjectId,
    required: true
  },
  url: {
    type: String,
    trim: true,
    required: true
  },

...

  title: {
    type: String,
    trim: true,
    required: false
  },
  description: {
    type: String,
    trim: true,
    required: false
  }
});

mongoose.model('Bookmarks', BookmarksSchema);

мой метод создания:

const mongoose = require('mongoose');
const passport = require('passport');
const router = require('express').Router();
const auth = require('../auth');
const Bookmarks = mongoose.model('Bookmarks');

router.post('/', auth.required, (req, res, next) => {
  const userId = req.user.id;
  const bookmark = req.body.bookmark;

  if (!bookmark.url) {
    return res.status(422).json({
      errors: {
        url: 'is required',
      },
    });
  }

  const { getMetadata } = require('page-metadata-parser');
  const domino = require('domino');

  const url = bookmark.url;
  const response = fetch(url);
  const html = response.text();
  const doc = domino.createWindow(html).document;
  const metadata = getMetadata(doc, url);

  bookmark.userId = userId;
  bookmark.title = metadata.title;
  bookmark.description = metadata.description;

  const finalBookmark = new Bookmarks(bookmark);

  return finalBookmark.save()
    .then(() => res.json({ bookmark: finalBookmark }));
});

и package.json:

{
  "name": "server",
  "version": "1.0.0",
  "description": "",
  "main": "app.js",
  "dependencies": {
    "body-parser": "^1.18.3",
    "cors": "^2.8.5",
    "domino": "^2.1.3",
    "errorhandler": "^1.5.0",
    "express": "^4.16.4",
    "express-jwt": "^5.3.1",
    "express-session": "^1.15.6",
    "jsonwebtoken": "^8.5.1",
    "mongoose": "^5.4.20",
    "morgan": "^1.9.1",
    "page-metadata-parser": "^1.1.3",
    "passport": "^0.4.0",
    "passport-local": "^1.0.0",
    "path": "^0.12.7"
  },
  "devDependencies": {},
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "nodemon app"
  },
  "author": "",
  "license": "ISC"
}

1 Ответ

0 голосов
/ 10 апреля 2019

Размещение ответа здесь, чтобы мы могли пометить ответ как правильный.

Ошибка возникла из-за того, что вызов fetch() был асинхронным, а ключевое слово await не использовалось. Пример на сайте NPM находится здесь:

https://www.npmjs.com/package/page-metadata-parser

Показывает, что они использовали await при вызове fetch(). Чтобы использовать await анонимную функцию обратного вызова, функция, начинающаяся с (req, res, next), должна иметь ключевое слово async перед ней. Вызов должен выглядеть следующим образом:

router.post('/', auth.required, async (req, res, next) => {
     // Do your stuff here as before.
     const url = bookmark.url;
     const response = await fetch(url);
     const html = response.text();
     const doc = domino.createWindow(html).document;
     const metadata = getMetadata(doc, url);
     // Finish stuff here.
});

Теперь ответ заполняется, и программа ожидает завершения вызова fetch, прежде чем двигаться вперед, заполняя оставшиеся переменные и имея возможность получить метаданные.

...