简体   繁体   English

具有API和数据库查询的Node.js Promise Chain

[英]Node.js Promise Chain with API and database query

I am pretty new to the whole promises business and am trying out my project with them. 对于整个承诺业务,我还很陌生,正在与他们一起尝试我的项目。
No I need to query an external API, go several items in the response, do other checks on my own database with them and when all of them are finished, need to resolve the whole promise in itself. 否,我需要查询外部API,在响应中进行几个操作,并在它们自己的数据库上进行其他检查,当所有这些操作完成时,需要自己解决整个承诺。
I also need even another call to my database at the marked point with another promise. 我甚至还需要在另一个标记处以另一个承诺再次调用我的数据库。 These are independent from each other but the "parent" promise should only resolve when both are resolved. 它们彼此独立,但是“父母”承诺只应在双方都解决后才能解决。
I am at a wall here and probably need some general explanation about chaining several promises with multiple items. 我在这里碰壁,可能需要一些有关将多个promise与多个项目链接在一起的一般解释。
Maybe I just understand something generally wrong here... Here is my code so far (shortened at ...): 也许我只是在这里理解普遍存在的问题...这是到目前为止的代码(在...处简称):

'use strict';

import rp from 'request-promise';
import _ from 'lodash';

var Import = {
  init: function(user, options) {
    return new Promise((resolve, reject) => {
      rp.get("...") // call to external API
        .then((res) => {
          ...
          resolve();
        });
      ...
    });
  },
  run: function() {
    return new Promise((resolve, reject) => {
      ...

      rp.get(...) // call to external API
        .then((res) => {
          var events = JSON.parse(res).data;
          var promises = [];

          for (var i = 0; i < events.length; i++) {

            promises.push(new Promise((resolve, reject) => {
              ...

              Location.findOneAndUpdateAsync(...)
                .then((loc) => {
                  events[i].location = loc._id;
                  resolve();
                })
                .catch((err) => {
                  console.error(err);
                  reject();
                });

              // I need even another call to my database here later with another promise
            }));
          }
          return Promise.all(promises)
            .then(() => {
              console.log("all promises resolved");
              resolve(events);
            });
        })
        .catch((err) => {
          console.error(err);
          reject(err);
        });
    });
  }
};

You can dramatically simplify your code by not falling foul of the Promise constructor anti-pattern - the functions you're calling already return promises so you should take advantage of those. 您可以通过不违反Promise构造函数反模式来极大地简化代码-您正在调用的函数已经返回诺言,因此您应该利用这些诺言。

Then, eliminate the for / push loop with Array.prototype.map : 然后,使用Array.prototype.map消除for / push循环:

var promises = events.map(function(event) {
    return Location.findOneAndUpdateAsync(...)
            .then((loc) => event.location = loc._id);
});

You said you have two sets of calls to make, but as they're independent, you might as well just use another .map call: 您说过要进行两组调用,但是由于它们是独立的,因此您最好只使用另一个.map调用:

var promises2 = events.map(function(event) {
    return ...
});

and then you just need to wait for all of those and return your events object: 然后您只需要等待所有这些并返回您的events对象即可:

return Promise.all(promises.concat(promises2)).then(() => events);

There's no need for all those .catch blocks - you should let the error propagate upwards. 不需要所有这些.catch块-您应该让错误向上传播。

If (per your comments) the two inner calls have a dependency, you could try this: 如果(根据您的评论)两个内部调用具有依赖性,则可以尝试以下操作:

var promises = events.map(function(event) {
    return Location.findOneAndUpdateAsync(...)
           .then((loc) => {
               event.location = loc._id;
               if (condition) {
                   return XXXOtherFunctionReturningPromise();
               }
           });
});

[and obviously then eliminate the .concat call from above] [并且显然从上面消除了.concat调用]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM