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

#javascript #react-native #async-await

#javascript #реагировать -родной #async-ожидание

Вопрос:

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

 async donglePaired(){
    if (Platform.OS !=='ios'){
        var pairedDevices = await BluetoothScanner.getPairedDevices();
        console.log('Sending........');
        let data={
            data:pairedDevices,
        };
        new Api().fetch("bluetoothCheck",{devices:JSON.stringify(data),userid:this.state.probe.UID},(result) => {
            if (!result.err) return false;
            console.log("Dongle already paired");
            return true;
            //logNetworkState
        });

    }

}
 

Это функция Api.fetch, которую я написал

 fetch(action,data,cb){
    let url=Config.URL "?version=" Config.VERSION "amp;action=" action;
    let post="";
    let formData=new FormData();
    for(let k in data) formData.append(k,data[k]);
    for(let k in data) post ="amp;" k "=" encodeURIComponent(data[k]).replace(/ /g,' ');
    console.log(url post);
    console.log(url);
    if (data.batch) console.log(data.batch);
    let sending=true;
    fetch(url,{
        method: 'post',
        body: formData
    })
    .then(function(response){
        if (true) return response.json();
        let txt=response.text();
        console.log(txt);
        return JSON.parse(txt);
    })
    .then(
        (result)=>{
            if (!sending) return;
            sending=false;
            console.log(JSON.stringify(result));
            if (cb) cb(result);
        },
        (error)=>{
            if (!sending) return;
            sending=false;
            console.log("fetch error");
            console.log(error);
            if (cb) cb();
        }
    );
    setTimeout(()=>{
        console.log("http timeout")
        if (!sending) return console.log("nothing to abort");
        if (cb) cb();
    },Config.HTTP_TIMEOUT*1000)

}
 

}

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

 let donglePaired = await this.props.app.donglePaired();
    if (donglePaired) return this.props.app.setError("ERR_DONGLE");
 

Проблема в том, что программа не ожидает подключения ключа, несмотря на ожидание

Комментарии:

1. Куда вы добавили let donglePaired часть? Это асинхронный метод?

2. не могли бы вы добавить журналы, которые вы получаете, по порядку

Ответ №1:

ваш код здесь неуместен

 let donglePaired = await this.props.app.donglePaired();
if (donglePaired) return this.props.app.setError("ERR_DONGLE");
 

Асинхронная функция не может нормально возвращать значение, если оно не является обещанием
Смотрите мою простую демонстрацию ниже!

 async function test() {
  const result = await asyncRequest()
  return result
}

function asyncRequest() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('success')
    }, 2000)
  })
}

test().then((data) => {
  console.log(data)
})
 

Ответ №2:

Фрагменты должны дать вам представление о том, как ожидать обратного вызова

Отправка в API

 async function remove_configuration(filename) {

const data = { filename };
const options = {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json'
    },
    body: JSON.stringify(data)
};
    await fetch('/delete', options);
 

}

Просто получение данных

 async function display() {
    
        let response = await fetch('/get-available-configurations')
        let data = await response.json(); // JSON or Text what do you prefer
         // do something with data
}
 

Ответ №3:

Вы могли бы вернуть Promise.race() функцию с таймаутом.

 fetch(action, data, cb) {
  let url = Config.URL   "?version="   Config.VERSION   "amp;action="   action;
  let post = "";
  let formData = new FormData();
  for (let k in data) formData.append(k, data[k]);
  for (let k in data)
    post  = "amp;"   k   "="   encodeURIComponent(data[k]).replace(/ /g, " ");
  console.log(url   post);
  console.log(url);
  if (data.batch) console.log(data.batch);
  let sending = true;
  return Promise.race([
    fetch(url, {
      method: "post",
      body: formData
    })
      .then(res => res.json())
      .then(result => {
        if (!sending) return;
        sending = false;
        return resu<
      }),
    sleep(Config.HTTP_TIMEOUT * 1000)
  ]);
}

const sleep = ms => new Promise((_, rej) => setTimeout(rej("TIMEOUT"), ms));
 

Он либо возвращает вам значение, либо отклоняет с TIMEOUT помощью, либо отклоняет с ошибкой из выборки

И donglePaired тогда выглядит так. Я обернул его с помощью try / catch

 async donglePaired() {
  if (Platform.OS !== "ios") {
    var pairedDevices = await BluetoothScanner.getPairedDevices();
    console.log("Sending........");
    let data = {
      data: pairedDevices
    };
    try {
      let result = await new Api().fetch("bluetoothCheck", {
        devices: JSON.stringify(data),
        userid: this.state.probe.UID
      });

      if (!result.err) return false;
      console.log("Dongle already paired");
      return true;
      //logNetworkState
    } catch (err) {
      console.log(err);
    }
  }
}
 

Ответ №4:

Одна из возможностей — удалить async и изменить его на this:

    donglePaired() {
        return new Promise( function(resolve, reject) { 
            if (Platform.OS !=='ios'){
              var pairedDevices = await BluetoothScanner.getPairedDevices();
              console.log('Sending........');
              let data={
                  data:pairedDevices,
              };
              new Api().fetch("bluetoothCheck",{devices:JSON.stringify(data),userid:this.state.probe.UID},(result) => {
                  if (!result.err) reject(false);
                  console.log("Dongle already paired");
                  resolve(true);
                  //logNetworkState
              });
            }
            reject(false);
        });  
     }
 

И:

 this.props.app.donglePaired().then( (response) => { 
  // do something here, this will only run if the response is true
});