Завершить выполнение функции рекурсивного обещания в Javascript - PullRequest
0 голосов
/ 05 декабря 2018

У меня есть 3 функции, func1 () возвращает некоторые API-данные в func2 (), и func2 () вызывается из func3 (). Func2 () имеет тип возврата Promise, в Func2 () я разрешаю только некоторые условия:встретил еще, я хочу вызывать ту же Func2 (), пока не будет выполнено условие, но когда я выполняю func3 (). Я не вижу своего ответа от func2 (). Я получаю сообщение об ошибке «Аргумент обратного вызова» должен быть функцией: TypeError: «callback»аргумент должен быть функцией.

//func1()
const apiRequest = (options, func_callback) => {
  request(options, (err, res, body) => {
    let result = {
      body: body,
      error: err,
      res: res
    }
    func_callback(result);
  });
};
//func2
const getPromise = (options) => {
  return new Promise((resolve, reject) => {
    apiRequest(options, (response) => {
      if (response.error) {
        reject(response.error);
      }
      if (response.body.hasOwnProperty('message')) {
        console.error(`Error: Invalid token`);
        new Promise((resolve, reject) => {
          const payload = {
            url: 'https://abc',
            form:{},
            method: 'post'
          };
          request(payload, (err, res, body) => {
            if (err) {
              reject(err);
            }
            else {
              resolve(body);
            }
          });
        }).then((result) => {

          options.headers.Authorization = 'Bearer '+result;
          getPromise(options); // seems Issue having this line to call again
        });
      }
      else {
        resolve(response.body);
      }
    });
  });
};

// func3()
function getSession() {
  const options={url:''someurl',     
  getPromise.then(result => {
    console.log('all ID'+result); // I can not see result here
  .catch(error => {
    console.log('Error ', error);
  });
}

Ответы [ 3 ]

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

Единственное место, где должно быть создано обещание, - это функция, заключающая в себе apiRequest.Эта оболочка («обещание») не должна делать ничего, кроме создания обещания, которое разрешается внутри обратного вызова.

//func1()
const apiRequest = (options, func_callback) => {
    request(options, (err, res, body) => {
        let result = {
            body: body,
            error: err,
            res: res
        }
        func_callback(result);
    });
};

// wrap the apiReqeust function in a promise.  place no other logic in here...
const apiRequestP = (options) => {
    return new Promise((resolve, reject) => {
        apiRequest = (options, response => {
            (response.error)? reject(response.error) : resolve(response);
        })
    });
};

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

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

// return a promise to make a token request followed by an auth'd version
// of the request described in the options param
const remediateAuth = (options) => {
    console.error(`Error: Invalid token`);
    const authOptions = { url: 'https://abc', form:{}, method: 'post' };
    return apiRequestP(authOptions).then(response => {
        options.headers.Authorization = 'Bearer '+response;
        return apiRequestP(options);
    }).then(response => response.body);
}

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

// was called func2
const authedRequest = (options) => {
    return apiRequestP(options).then(response => {
        return (response.body.hasOwnProperty('message'))? remediateAuth(options) : response.body;
    });
}
0 голосов
/ 05 декабря 2018

В условии if, где вы создаете new Promise(…).then(…), вы никогда не разрешите внешнее обещание.

Вы можете решить это, добавив resolve в нужных местах, но вам не следует создаватьобещания в пределах обещаний в любом случае.Вы должны обещать на самом низком уровне.Заставьте api_request возвращать обещание, а не принимать обратный вызов.

// func1()
function apiRequest(options, func_callback) {
  return new Promise((resolve, reject) => {
    request(options, (err, res, body) => {
      if (err) reject(err);
      else resolve({ body, res });
    });
  });
}

Вы можете даже использовать его повторно и использовать правильную цепочку обещаний:

//func2
functon getPromise(options) {
  return apiRequest(options).then(response => {
    if (response.body.hasOwnProperty('message')) {
      console.error(`Error: Invalid token`);
      const payload = {
        url: 'https://abc',
        form:{},
        method: 'post'
      };
      return apiRequest(payload).then(result => {
        options.headers.Authorization = 'Bearer '+result.body;
        return getPromise(options); // seems Issue having this line to call again
      });
    } else {
      return response.body;
    }
  });
}
0 голосов
/ 05 декабря 2018

кажется, что в вашей функции 'getPromise' вы получаете (разрешить, отклонить), но затем внутри функции вы создаете еще одно обещание, а затем вы создаете еще две переменные с именем (разрешить, отклонить), которые переопределяют исходное разрешение, а затему вас действительно нет никакого возвращаемого значения из getPromise

Первое назначение:

const getPromise = (options) => {
      return new Promise((resolve, reject) => {

и второе назначение:

console.error(`Error: Invalid token`);
            new Promise((resolve, reject) => {
...