Вызывающий не получает правильное значение из асинхронного метода с ajax - PullRequest
0 голосов
/ 25 февраля 2019

Я пытаюсь обернуть мой вызов ajax обещанием.Поэтому, когда вызов ajax завершен, обещание разрешается.

В следующем фрагменте:

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 из getDetails().result в test () - это объект обещания, а не ожидаемое значение.

Как получить асинхронное значение из getDetails с помощью Promises?

Ответы [ 2 ]

0 голосов
/ 25 февраля 2019

Когда вы объявляете функцию как async, она неявно возвращает Promise, если это явно не сделано.Это означает, что ваша getDetails функция всегда будет возвращать Promise.Таким образом, вам нужно либо использовать обратный вызов .then, чтобы получить результат из getDetails, либо использовать await, чтобы «распаковать» результат из обещания.

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

Документация по jQuery API :

jqXHRобъекты, возвращаемые $ .ajax () начиная с jQuery 1.5, реализуют интерфейс Promise, предоставляя им все свойства, методы и поведение Promise ...

Это означает, что ваш запрос ajax будет resolve и reject для вас, и, таким образом, позволяет обрабатывать возвращаемое значение как 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 может сделать работу за вас.

0 голосов
/ 25 февраля 2019

Это потому, что getDetails(...) возвращает обещание, а не параметр, переданный в обратные вызовы 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, вы можете рассмотреть возможность с использованием 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();
...