函数在ajax调用for循环结束之前返回

时间:2019-01-21 04:26:06

标签: javascript typescript asynchronous async-await es6-promise

我在使用for循环结束的ajax调用之前返回的函数遇到了一些麻烦。我进行了几次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 :(得分:1)

您的request包装器不是很好,不幸的是,亚伦的包装器并没有更好。近年来,我没有使用太多jQuery,但我认为它现在也具有基于Promise的API。无论哪种方式,您都需要某种通用的东西,它基本上为您提供$.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))
    )

您尚未提供Minimum, Complete, Verifiable Example (MVCE),因此很难为您提供帮助。我们不了解timescheckStep,因此对您的意图进行了一些猜测。这样的事情可能会帮助您重新转动车轮-

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, ... }, ... ]

  // ...
}

答案 1 :(得分:0)

类似的事情应该起作用

@ModelAttribute @Valid MyBean myBean

此外,您还为函数指定了返回类型,是否要使用TypeScript?不知道Promise返回类型是否有效。但想法是您需要兑现承诺。