Как правильно связать обещания используя - PullRequest
0 голосов
/ 10 декабря 2018

У меня есть система, которая хочет создать много папок в Dropbox, используя API, однако я, кажется, пытаюсь создать все папки сразу, что вызывает ошибки, утверждая, что я выполняю слишком много операций записи из Dropbox.

Мой код выглядит следующим образом, и вначале использует сокращение, чтобы создать несколько обещаний, которые, как я думал, были прикованы цепью.В этих обещаниях вызывается функция add, которая загружает регистр в mongodb, а затем создает для него папку dropbox, однако это приводит к ошибкам регулирования ..

bulkAdd: function (req, callback) {
  issues = []
  i = 1

  req.reduce((promise, audit) => {
    return promise.then(_ => this.add(audit, function(err,data){
      if (err){
        console.log('\n'+i+ ' ' + data.scanner_ui + '\n');
      }
    }));
  }, Promise.resolve()).catch(error => {console.log(error)});
},

add: function (req, callback) {
  delete req.status
  var audit = new Audit(req);
  if (req['status_value'] != undefined && req.status_value != ''){
    console.log(req['status_value'])
    audit.status = [{
      status_value : req['status_value'],
      status_notes : req['status_notes'],
      status_date : req['status_date'],
    }]
  }

  audit.save(function (err, data) {
    if (err) {
      callback(err, data)
    }
    else {
        return dropbox_functions.createFolder(data.ui)
          .then(response => {console.log(response)}, error=> {console.log('\n\n\n',error.error.error)})
        .catch(error => console.log(error))
    }
  }); 

},

Ответы [ 3 ]

0 голосов
/ 10 декабря 2018

Для правильной цепочки вы должны убедиться, что вы возвращаете объект обещания.

Ваше сокращение в конце создает цепочку обещаний примерно так.

Promise.resolve()
    .then(() => {
        console.log('setting up first timeout');
        setTimeout(() => {
            console.log("1 wait");
        }, 2000);
    })
    .then(() => {
      console.log('setting up second timeout');
        setTimeout(() => {
            console.log("2 wait");
        }, 2000);
    })
    .catch(err => console.log("error", err));

Если вы запустите его, вы увидите, что оно не дожидается окончания одного обещания, прежде чем двигаться по цепочке.

Принимая во внимание, что вво втором примере он ожидает завершения первого, потому что объект Promise возвращается первым обещанием.

Promise.resolve()
  .then(() => {
    return new Promise(function(resolve, reject) {
      console.log('setting up first timeout');
      setTimeout(() => {
        console.log("1 wait");
        resolve();
      }, 2000);
    });
  })
  .then(() => {
    return new Promise(function(resolve, reject) {
      console.log('setting up second timeout');
      setTimeout(() => {
        console.log("2 wait");
        resolve();
      }, 2000);
    });
  })
  .catch(err => console.log("error", err));

Разница в том, что первый пример не возвращает объект Promise.Итак, если вы убедитесь, что каждый обработчик успеха возвращает объект Promise, который разрешается только после того, как ваша функция добавления завершена, у вас все будет в порядке.

0 голосов
/ 10 декабря 2018

Если нет веских оснований для написания bulkAdd() в стиле nodeback, вам будет удобнее вернуть обещание.Потребность в нодбеке исчезнет, ​​и .reduce() будет гораздо удобнее сидеть внутри функции.

Использование .reduce() и сохранение стиля нодбэка возможно, но громоздко, поскольку в нем задействовано довольно уродливое двойное перемешивание от нодбека к обещанию и обещание обратно к нодбеку.

Предполагается, что вы свободныАдаптируйте вызывающего абонента для принятия возвращенного обещания, код будет выглядеть примерно так:

'bulkAdd': function(req) {
    return req.reduce((promise, audit) => {
        return promise.then(_ => this.add(audit));
    }, Promise.resolve());
},
'add': function(req) {
    delete req.status;
    var audit = new Audit(req);
    if (req.status_value != undefined && req.status_value != '') {
        audit.status = [{
            'status_value': req.status_value,
            'status_notes': req.status_notes,
            'status_date': req.status_date
        }];
    }
    return new Promise((resolve, reject) => { // in-line promisification of audit.save()
        audit.save((err, data) => {
            err ? reject(err) : resolve(data);
        });
    })
    .then(data => dropbox_functions.createFolder(data.ui));
},

все перехваты и записи намеренно удалены

Детали могутразличаются, в основном в зависимости от:

  • какие данные (если таковые имеются) вы хотите доставить вызывающей стороне
  • что вы хотите, чтобы происходить при возникновении ошибок.
0 голосов
/ 10 декабря 2018

Итак, проблема в вашем текущем вопросе связана с тем, что ваша add функция не возвращает значение, я вижу, что она возвращает неопределенное значение.

Если обещание возвращает что-то еще, кроме обещания вего блок then / catch, он будет использовать этот вход для следующей функции и не будет ждать прохождения внутренних процессов, прежде чем завершить

Если внутри вашего then / catchблоки, вы бы вернули обещание, он подождет, прежде чем перейти к следующему then блоку, таким образом обрабатывая ваши запросы последовательно.

Теперь в вашем текущем коде, я полагаю, проще всего было бы обработать разрешение внутриваше сокращение, поскольку вы, похоже, уже застряли с дескриптором обратного вызова.

req.reduce((promise, audit) => {
  return promise.then(_ => new Promise( 
    function( resolve, reject) {
      this.add(audit, function(err,data){
        if (err){
          console.log('\n'+i+ ' ' + data.scanner_ui + '\n');
          reject( err );
          return;
        }
        resolve( data );
      });
    })
  );
}, Promise.resolve()).catch(error => {console.log(error)});

в этом случае обещание будет либо reject, либо resolve.Я решил отправить err и data соответственно, так что это будет обработано в конце, если произойдет ошибка, и вы сможете получить последние данные, которые были успешно сохранены

...