调用者无法从使用Ajax的异步方法获取正确的值

时间:2019-02-25 13:04:13

标签: javascript ajax promise async-await

我正在尝试将我的Ajax调用包装在Promise周围。因此,当ajax调用完成时,promise就会解决。

在以下代码段中:

async function getDetails (data){   
      let promise = new Promise((resolve, reject) => {      
          $.ajax({
                  url: "/get-details",
                  type:"get",
                  contentType:"application/json",
                  data:{"text":data},
                  success: function(result){
                    resolve(result.response);
                  },
                  error: function(result){
                    reject(result.response);
                  }
          });
      });
    let result = await promise;
    console.log(`result: ${result}`);
    return result;
}

function test() {
    let result = getDetails("query-text");
    console.log(`result in test : ${result}`);
}

test();

我在result的{​​{1}}中得到了正确的值。 test()中的getDetails()是一个Promise对象,而不是期望值。

如何使用Promises以异步方式从getDetails获得所需的值?

2 个答案:

答案 0 :(得分:3)

那是因为getDetails(...)返回一个promise,而不是传递到resolve()reject()回调中的参数。因此,这样做应该可以:

async function test() {
    let result = await getDetails("query-text");
    console.log(`result in test : ${result}`);
}

或者,您也可以不使用async方法,只需等待诺言解决即可:

function test() {
    let p = getDetails("query-text");
    p.then(result => console.log(`result in test : ${result}`));
}

甚至更好:使用新的fetch() API

由于您使用的是ES6,因此您可能还是要考虑using the fetch() API

async function getDetails (data){   
  let result = await fetch('/get-details').then(resp => resp.json());
  console.log(`result: ${result.response}`);
  return result.response;
}

async function test() {
  let result = await getDetails("query-text");
  console.log(`result in test : ${result}`);
}

test();

答案 1 :(得分:1)

在将函数声明为async时,如果未明确声明,则它将隐式返回Promise。这意味着您的getDetails函数将始终返回Promise。因此,您需要使用.then回调从getDetails获取结果,或使用await从承诺中“解包”。

您可以在代码中更改的另一件事是,您无需将ajax请求包装在promise中:

jQuery API Documentation

  

从jQuery 1.5开始,由$ .ajax()返回的jqXHR对象实现了   Promise接口,为他们提供所有属性,方法和   承诺的行为...

这意味着您的ajax请求将为您resolvereject,从而使您可以将返回值视为Promise,从而可以将promise变量设置为直接相等到您的Ajax请求:

async function getDetails(data) {

  let promise = $.ajax({
    url: "/get-details",
    type: "get",
    contentType: "application/json",
    data: {
      "text": data
    }
  });

  let result = await promise;
  console.log(`result: ${result}`);
  return result; // returns a new promise with the return value as the resolve
}

async function test() {
  let result = await getDetails("query-text"); // await to "unpack" the promise returned via your async function "getDetails"
  console.log(`result in test : ${result}`);
}

test();

但是,正如 @Terry 所指出的那样,如果您仅使用jQuery发送Ajax请求,则实际上没有必要(除非您真的担心浏览器支持) 。 fetch可以为您完成这项工作。