augustin
augustin

Reputation: 69

problem awaiting the callback given to a function

I have a function who send a message to the server to get the answer and if the answer is true I want my application to send an error to the user. The problem is that I can't manage to await the callback in the Fetch function I wrote. This is the function who send the question to the server.

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
        });

    }

}

This is the Api.fetch function i wrote

fetch(action,data,cb){
    let url=Config.URL+"?version="+Config.VERSION+"&action="+action;
    let post="";
    let formData=new FormData();
    for(let k in data) formData.append(k,data[k]);
    for(let k in data) post+="&"+k+"="+encodeURIComponent(data[k]).replace(/%20/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)

}

}

And this is my main code where I wait for the first function donglePaired, and if donglePaired return true I send an error to the user.

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

The problem is that the program doesnt wait for donglePaired, despite of the await

Upvotes: 2

Views: 124

Answers (4)

TimonNetherlands
TimonNetherlands

Reputation: 1053

One possibility is to drop the async and change it to 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);
        });  
     }

And:

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

Upvotes: 0

Ilijanovic
Ilijanovic

Reputation: 14904

You could return an Promise.race() with your timeout function.

fetch(action, data, cb) {
  let url = Config.URL + "?version=" + Config.VERSION + "&action=" + action;
  let post = "";
  let formData = new FormData();
  for (let k in data) formData.append(k, data[k]);
  for (let k in data)
    post += "&" + k + "=" + encodeURIComponent(data[k]).replace(/%20/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 result;
      }),
    sleep(Config.HTTP_TIMEOUT * 1000)
  ]);
}

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

It either returns you the value or it rejects with TIMEOUT or it rejects with an error from fetch

And donglePaired looks like this then. I have wrapped it with an 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);
    }
  }
}

Upvotes: 1

user8294160
user8294160

Reputation:

The snippets should give you an idea how to await the callback

Sending to the 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);

}

Just Retrieving Data

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
}

Upvotes: 1

fbfatboy
fbfatboy

Reputation: 401

your code here is inappropriate

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

Async function cannot return value normally unless it is a Promise See my simple demo below!

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)
})

Upvotes: 1

Related Questions