Используйте cancel() внутри цепочки then, созданной promisifyAll

Не уверен, что я достаточно ясен с этим названием, но предположим, что у меня есть класс с именем Foo method1, method2 а также method3, Я обещаю его методы с promisifyAll,

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

Я читал об отмене ( http://bluebirdjs.com/docs/api/cancellation.html), но я не знаю, как реализовать это с promisifyAll.

Код, который я получил, плюс то, что мне нужно:

var bluebird = require('bluebird');

function Foo() { }

Foo.prototype.method1 = function (cb) {};

Foo.prototype.method2 = function (cb) {};

Foo.prototype.method3 = function (cb) {};

var foo = bluebird.promisifyAll(new Foo());

foo.method1Async()
.then(function (r1) {
  // cancel then-chain
  res.json("Task stopped");
  // just stop right here
  promises.cancel();
})
.then(function (r2) {
  console.log(r2);
}).then(function (r3) {
  console.log(r3);
})
.catch(function (er) {
  console.log('Catch!');
});

Как правильно получить этот результат? Я знаю, что могу просто бросить что-нибудь и поймать это в catch метод, но это внесет очень большие изменения в моем реальном коде.

1 ответ

Решение

Попробуйте что-то вроде этого:

var bluebird = require('bluebird');

function Foo() { }

Foo.prototype.method1 = function (cb) { cb(null, 'method1'); };
Foo.prototype.method2 = function (cb) { cb(null, 'method2'); };
Foo.prototype.method3 = function (cb) { cb(null, 'method3'); };

var foo = bluebird.promisifyAll(new Foo());

foo.method1Async()
.then(function (r1) {
  console.log('step 1');
  // cancel then-chain
  console.log("Task stopped");
  // just stop right here
  return bluebird.reject('some reason');
})
.then(function (r2) {
  console.log('step 2');
  console.log(r2);
}).then(function (r3) {
  console.log('step 3');
  console.log(r3);
})
.catch(function (er) {
  console.log('Catch!');
  console.log('Error:', er);
});

Вместо:

  return bluebird.reject('some reason');

ты можешь использовать:

  throw 'some reason';

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

Обновление 1

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

var bluebird = require('bluebird');

function Foo() { }

Foo.prototype.method1 = function (cb) { cb(null, 'method1'); };
Foo.prototype.method2 = function (cb) { cb(null, 'method2'); };
Foo.prototype.method3 = function (cb) { cb(null, 'method3'); };

var foo = bluebird.promisifyAll(new Foo());

foo.method1Async()
.then(function (r1) {
  console.log('step 1');
  console.log('got value:', r1);
  // cancel? change to true:
  var cancel = false;
  if (cancel) {
    console.log("Task stopped");
    return bluebird.reject('some reason');
  } else {
    console.log('Keep going');
    return foo.method2Async();
  }
})
.then(function (r2) {
  console.log('step 2');
  console.log('got value:', r2);
  return foo.method3Async();
}).then(function (r3) {
  console.log('step 3');
  console.log('got value:', r3);
})
.catch(function (er) {
  console.log('Catch!');
  console.log('Error:', er);
});

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

Обновление 2

Еще один пример, который не вызывает последний catch для этого случая:

foo.method1Async()
.then(function (r1) {
  console.log('step 1');
  console.log('got value:', r1);
  // cancel? change to true:
  var cancel = true;
  if (cancel) {
    console.log("Task stopped");
    return bluebird.reject('some reason');
  } else {
    console.log('Keep going');
    return foo.method2Async();
  }
})
.then(function (r2) {
  console.log('step 2');
  console.log('got value:', r2);
  return foo.method3Async();
}).then(function (r3) {
  console.log('step 3');
  console.log('got value:', r3);
})
.catch(function (er) {
  if (er === 'some reason') {
    return bluebird.resolve('ok');
  } else {
    return bluebird.reject(er);
  }
})
.catch(function (er) {
  console.log('Catch!');
  console.log('Error:', er);
});

объяснение

Думайте об этом так: в синхронном коде, если у вас есть:

r1 = fun1();
r2 = fun2();
r3 = fun3();

тогда единственный способ для fun1 отменить выполнение fun2 и fun3 - это создать исключение. И аналогично для обещаний, единственный способ, которым один then Обработчик может отменить выполнение следующего then Обработчик должен вернуть отклоненное обещание. И так же, как в синхронном коде, это исключение будет поймано catch блок, здесь это отклоненное обещание будет передано catch обработчик.

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

Это то, что происходит с кодом в обновлении 2. Причина отклонения сравнивается с некоторым значением (которое 'some reason' в этом примере), и если оно равно, то возвращается разрешенное обещание, и поэтому следующий catch обработчик не вызывается. Если она не равна, то причина отказа возвращается снова, поскольку ведьма, получившая отказ, затем передается следующему. catch обработчик как "настоящая" ошибка, которую вы хотите, чтобы последний catch обработчик для обработки.

Другие вопросы по тегам