环回 - "next()" 未在 "beforeRemote" 的正确时间触发?

loopback - "next()" not firing at the correct time in "beforeRemote"?

我正在尝试在 find 方法返回结果之前从远程源更新数据库。我正在尝试对 "find" 操作使用 "beforeRemote" 方法。它正在更新数据库,但不会等到数据库更新完成才返回数据。我可以这么说,因为我第一次针对空数据库调用 "find" 端点时,结果是空的,但是在调用之后检查数据库时,它里面有数据。

这是我的模型class(删除了敏感内容)。

'use strict';
var Cronofy = require('cronofy');
var _ = require('lodash');

module.exports = function (Event) {

  // remote method before hook
  Event.beforeRemote('find', function (ctx, unused, next) {
    var client = new Cronofy({
      access_token: 'secret-token',
    });

    var options = {
      from: "2018-10-15",
      to: "2018-11-15",
      tzid: 'Etc/UTC'
    };


    client.readEvents(options)
      .then(function (response) {
        var returnedEvents = response.events;
        var events = _.filter(returnedEvents, function(o){
          return !_.isEmpty(o.summary) && !_.isEmpty(o.event_uid) && !_.isEmpty(o.start) && !_.isEmpty(o.end);
        });

        events.forEach(element => {
          Event.upsertWithWhere({
              sourceType: "external-source-a",
              sourceID: element.event_uid
            }, {
              sourceType: "external-source-a",
              sourceID: element.event_uid,
              summary: element.summary,
              description: element.description,
              start: element.start,
              end: element.end,
              recurring: element.recurring
            },
            function (err, model) {
              if (err) {
                console.log(err);
              }
              //console.log(model);
            }
          );
        });
        next();
      }).catch(console.log);
  });
};

我是环回的新手,所以我确定这是一个简单的错误。我做错了什么?

使用Promise.allPromise.all

在更新的情况下,您不应将 forEach 与异步操作一起使用,因为 forEach 不会等到更新完成后再调用 next。 相反,例如使用 map 来循环事件和 return 更新操作的承诺,这样您就可以创建承诺数组并使用 Promise.all。 在then的Promise.all调用next方法。

    module.exports = function (Event) {

    // remote method before hook
    Event.beforeRemote('find', function (ctx, unused, next) {
      var client = new Cronofy({
        access_token: 'secret-token',
      });

      var options = {
        from: "2018-10-15",
        to: "2018-11-15",
        tzid: 'Etc/UTC'
      };

      client.readEvents(options)
        .then(function (response) {
          var returnedEvents = response.events;
          var events = _.filter(returnedEvents, function(o){
            return !_.isEmpty(o.summary) && !_.isEmpty(o.event_uid) && !_.isEmpty(o.start) && !_.isEmpty(o.end);
          });
          const updatepromises = events.map((element) => {
            return Event.upsertWithWhere({
              sourceType: "external-source-a",
              sourceID: element.event_uid
            }, {
                sourceType: "external-source-a",
                sourceID: element.event_uid,
                summary: element.summary,
                description: element.description,
                start: element.start,
                end: element.end,
                recurring: element.recurring
              });
          }); 
          return Promise.all(updatepromises); 

        })
        .then((result) => next())
        .catch(console.log);
    });
  };

或者您可以使用 async/await async/await,它更具可读性,您不必调用 next loopback 会为您处理。

    module.exports = function (Event) {
  // remote method before hook
  Event.beforeRemote('find', async function (ctx, unused) {
    var client = new Cronofy({
      access_token: 'secret-token',
    });
    var options = {
      from: "2018-10-15",
      to: "2018-11-15",
      tzid: 'Etc/UTC'
    };
    var response = await client.readEvents(options);
    var returnedEvents = response.events;
    var events = _.filter(returnedEvents, function (o) {
      return !_.isEmpty(o.summary) && !_.isEmpty(o.event_uid) && !_.isEmpty(o.start) && !_.isEmpty(o.end);
    });
    const updatepromises = events.map((element) => {
      return Event.upsertWithWhere({
        sourceType: "external-source-a",
        sourceID: element.event_uid
      }, {
          sourceType: "external-source-a",
          sourceID: element.event_uid,
          summary: element.summary,
          description: element.description,
          start: element.start,
          end: element.end,
          recurring: element.recurring
        });
    });
    await Promise.all(updatepromises);
  });
};