Функция возвращается до вызова ajax для завершения цикла - PullRequest
0 голосов
/ 21 января 2019

У меня возникли проблемы с функцией, которая возвращается до завершения цикла ajax из for.Я делаю несколько вызовов ajax, от которых получаю результат, и использую их в своей цепочке then.

Вот мой код

const delay = t => new Promise(resolve => setTimeout(resolve, t));
(async () => {
    await delay(timeout);
    let results: boolean[] = [];
    for (let i = 0; i < times; i++) {
        await this.ajaxService.postWithData("/api/v1/..",
            arg,
            (data) => {
                results[i] = this.checkStep(data);
            },
            () => {
            });
    }
    return results; // This returns before for loop containing ajaxServces calls ends
})().then((results) => {
    // Do some things here using `results`
});

postWithData

public request = (options: Options, successCallback: Function, errorCallback?: Function): void => {
        var that = this;
        $.ajax({
            url: options.url,
            type: options.method,
            data: options.data,
            cache: false,
            success: function (d) {
                successCallback(d);
            },
            error: function (d) {
                if (errorCallback) {
                    errorCallback(d);
                    return;
                }
            }
        });
    }

Я проверил SO ответы, например https://stackoverflow.com/a/40329190/3264998

Ответы [ 2 ]

0 голосов
/ 21 января 2019

ваша request оболочка не очень хорошая, и, к сожалению, Аарон не намного лучше.В последние годы я почти не пользовался jQuery, но думаю, что теперь у него есть API на основе Promise.В любом случае вам понадобится что-то общее, что в основном даст вам «обещанную» версию $.ajax, чтобы вы могли работать с await -

const defaultOpts =
  { method: 'GET', cache: false }

const request = (opts = {}) =>
  new Promise
    ( (resolve, reject) =>
        $.ajax({ ...defaultOpts, ...opts })
         .done((req, status, res) => resolve(res))
         .fail((req, status, err) => reject(err))
    )

Вы не предоставили Минимум,Полный, проверяемый пример (MVCE) , поэтому вам будет сложно помочь вам.Мы не знаем о times или checkStep, поэтому были сделаны некоторые предположения о ваших намерениях.Нечто подобное может помочь вам снова повернуть колеса -

const main = async () =>
{ const steps =
    [ request ("/api/v1/something..")
    , request ("/api/v1/another..")
    , request ("/api/v2/andthis..")
    ]

    const res =
      await Promise.all(steps)

   console.log(res)
    // [ <result1>, <result2>, <result3> ]

    // I don't know what your checkStep does
    // but something like this might work
    res.forEach(r => this.checkStep(r))

    // otherwise
    // const checked =
    //   res.map(r => this.checkStep(r))
    // ...

    return res
}

main()
  .then(res => console.log("all results", res))
  // [ <result1>, <result2>, <result3> ]
  .catch (e => ...)

Если один запрос зависит от другого, помещение запросов в массив и последующий вызов Promise.all не очень подходят.В приведенном ниже примере мы запрашиваем все сообщения для конкретного автора.Вымышленный API, к которому мы обращаемся, запрашивает у автора username, но мы знаем только id автора.В этом случае мы сначала ищем имя пользователя автора, , затем , мы можем запросить сообщения по имени пользователя -

const authorById = id =>
  request({ url: '/authors', data: { id } })

const postsByAuthor = username =>
  request ({ url: '/posts', data: { author: username } })

const main = () =>
{ const author =
    await authorById (10)
    // { id: 10, username: alice, email: alice@email.lol }

  // this request depends on the result of the first request
  const posts =
    await postsByAuthor (author.username)
    // [ { postId: 9, title: "hello world" }, { postId: 11, ... }, ... ]

  // ...
}
0 голосов
/ 21 января 2019

Как то так должно работать

public request = (options: Options, successCallback: Function, errorCallback?: Function): Promise => {
        return new Promise( (resolve, reject) => {
        var that = this;
        $.ajax({
            url: options.url,
            type: options.method,
            data: options.data,
            cache: false,
            success: function (d) {
                resolve(successCallback(d));

            },
            error: function (d) {
                if (errorCallback) {
                    reject(errorCallback(d));

                }
            }
        })};
    }

Кроме того, вы указали тип возврата для своей функции, будете ли вы использовать TypeScript? Не уверен, что тип возврата Promise действителен. Но идея в том, что вам нужно вернуть обещание.

...