Как конвертировать метод водопада, чтобы обещать

Ниже приведен фрагмент кода с использованием метода async-waterfall. Как я могу преобразовать это, используя обещание.

async.waterfall([
    function(callback){
     User.update({username: user.username}, {$set: update_list}, function(err, a_user) {
      if (err) {
        err = new Error();
        err.code = 400;
        err.message = "Unexpected error occurred."
        callback(err)
      }
      if (!a_user) {
        err = new Error();
        err.code = 400;
        err.message = "User not found."
        callback(err)
      }else{
        callback(null, "updated", user_image);
      }
    })
   }, function(message, user_image, callback){
    if(user_image == undefined){
      callback(null, "done")
    }else{
      Bean.update({username: user.username, status:"Active"}, {$set: {user_image:user_image}},{multi:true},function(err, beanUpdated){
        if(err){
          err = new Error();
          err.code = 400;
          err.message = "Unexpected error occurred."
          callback(err)
        }else{
          callback(null, "done"); 
        }
      })
    }
  }
  ], function(err, result){
    if(err){
      return res.json({code:err.code, message:err.message})
    }else{
      return res.json({code:200, message:"Successfully updated profile."})
    }
  })

Я обычно использую метод водопада и серии асинхронного модуля для синхронизации моего кода Node js. Помогите мне перейти от асинхронного к обещанию.

Ответ 1

Я не буду переписывать ваш код для вас, но я предоставлю вам достаточно информации, чтобы вы могли сделать это сами в трех разных стилях с примерами, демонстрирующими концепции. Переписывание кода даст вам хорошую возможность познакомиться с promises.

Вместо функций, выполняющих обратные вызовы и составляющих их с помощью async.waterfall, вы можете использовать функции, возвращающие promises, и вернуть эти promises из обратных вызовов then использовать разрешенные значения этих promises в следующем обратном вызове then:

f1().then((a) => {
  return f2(a);
}).then((b) => {
  return f3(b);
}).then((c) => {
  // you can use c which is the resolved value
  // of the promise returned by the call to f3(b)
}).catch((err) => {
  // handle errors
});

В этом простом примере можно упростить:

f1()
  .then(a => f2(a))
  .then(b => f3(b))
  .then((c) => {
    // use c here
  }).catch((err) => {
    // handle errors
  });

Или даже это:

f1().then(f2).then(f3).then((c) => {
  // use c here
}).catch((err) => {
  // handle errors
});

Или вы можете легко скомпоновать их вместе с async/await:

let a = await f1();
let b = await f2(a);
let c = await f3(b);
// ...

Или даже в этом конкретном случае:

let c = await f3(await f2(await f1()));

Здесь вы обрабатываете ошибки с помощью try/catch:

try {
  let c = await f3(await f2(await f1()));
  // use the c here
} catch (err) {
  // handle errors
}

Код с использованием await должен быть внутри функции, объявленной с ключевым словом async, но вы можете использовать ее где угодно, обернув что-то вроде этого:

// not async function - cannot use await here
(async () => {
  // this is async function - you can use await here
})();
// not async function again - cannot use await

Само выражение (async () => { ... })() возвращает обещание, которое разрешено к возвращаемому значению функции async или отклонено с исключенным изнутри исключением.

Обратите внимание, что в приведенных выше примерах каждая функция может легко зависеть от значения разрешенного обещания, возвращаемого предыдущей функцией, то есть точного варианта использования async.waterfall, но мы не используем для этого какую-либо библиотеку, а только собственные функции языка.

Синтаксис await доступен в Node v7.0 + с флагом гармонии и v7.6 + без каких-либо флагов. См:

Дополнительные примеры см. в этом ответе:

И для получения дополнительной информации см. обновления этого ответа для получения дополнительной информации: