суперагент/супертест с асинхронностью/ожиданием

Цель состоит в том, чтобы правильно установить переменную auth для дальнейшего использования, поэтому я хочу реорганизовать функцию loginUser:

function loginUser(user, request, auth) {
  return function(done) {
    request
      .post('/users/login')
      .send(credentials)
      .expect(200)
      .end(onResponse);

    function onResponse(err, res) {
      auth.token = res.body.token;
      return done();
    }
  };
}


 loginUser(user, request, auth)(function() {
  request.get(testUrl)
    .set('Authorization', `bearer ${auth.token}`)
    .expect(200, done);
});

использовать async/await следующим образом (без обратного вызова):

auth = await loginUser(user, request);
request.get(testUrl)
    .set('Authorization', `bearer ${auth.token}`)
    .expect(200, done);

Но я изо всех сил пытаюсь правильно вернуть/установить auth (не имеет значения, передам ли я auth как параметр или как возвращаемое значение).

То, что я пробовал, было примерно так:

async function loginUser(user, request) {
  let auth;
  await request
    .post('/users/login')
    .send(credentials)
    .expect(200)
    .end(onResponse);

  function onResponse(err, res) {
    auth.token = res.body.token;
  }
  return auth;
}

Но auth никогда не устанавливалось правильно.


person Gobliins    schedule 20.07.2018    source источник
comment
Возможный дубликат Promises es6 и superagent   -  person k0pernikus    schedule 20.07.2018
comment
хм, не уверен, так как я хочу избавиться от обратного вызова при вызове функции входа в систему   -  person Gobliins    schedule 20.07.2018


Ответы (2)


Не используйте синтаксис «конец», это для обратных вызовов:

const response = await request.post(...)
  .expect(200)
const {body: {token}} = response
return token

В основном это должно выглядеть как код синхронизации

person Lev Kuznetsov    schedule 20.07.2018
comment
Вы правы, но вы могли бы добавить некоторые детали в (...) у меня возникли проблемы с пониманием того, как переписать мой код. - person Gobliins; 01.08.2018
comment
Часть о const {body: {token}} = response была для меня немного запутанной, в итоге я попробовал const {response} = await..., что привело к неопределенному ответу. Выполнение let response = await... работало нормально. Просто оставлю это как примечание для всех, кто может запутаться в этом. Суперагент хорош, но синтаксис ожидания кажется немного недостаточным в примерах. В любом случае, теперь это работает. Я думаю, ваш пример просто касается конкретного вопроса OP при разборе токена из тела, и синтаксис для меня немного странный. - person kg_sYy; 21.12.2020

Проблема в том, что метод onResponse выполняется позже, чем вы возвращаете функцию из-за цикла событий в Nodejs. Таким образом, вам нужно будет выполнить обещание именно тогда, когда вы получите данные.

Метод loginUserInternal может быть таким:

function loginUserInternal(user, request) {
  return new Promise((resolve,reject) => {
    let auth = {};
    request
      .post('/users/login')
      .send({
        username: user.username,
        password: user.password_decoded,
      })
      .expect(200)
      .end(onResponse);
    function onResponse(err, res) {
      if(err) return reject(err)
      auth.id = res.body.id;
      auth.token = res.body.token;
      auth.tokenExpires = res.body.tokenExpires;
      resolve(auth)
    }
  })
}

И назовите это так же, как вы делали это с асинхронным ожиданием.

person David Viejo    schedule 20.07.2018
comment
Можете показать, как это назвать? Я всегда получаю тайм-аут 2000 мс, отклонение необработанного обещания или обещание {‹ожидание›}. Также onResponse требуется возвращаемое значение, когда ошибка не возникает или пропустить завершение возврата (я сделал это так). - person Gobliins; 20.07.2018
comment
Как и в вашем посте auth = await loginUser(user, request);, если он дает вам отказ от обещания, это означает, что запрос не выполнен, попробуйте выполнить console.log(err), чтобы увидеть, что происходит. - person David Viejo; 20.07.2018