pete
pete

Reputation: 359

JavaScript function(callback).then(), callback executes after then

I have trouble to get this to work.

I have a function getItem:

export const getItem = async (key, callback) => {
    value = await Expo.SecureStore.getItemAsync(key).catch((error) => console.log(error));
    callback(value);
}

getItem is supposd to get a token and pass that token to the callback.

Now I want to use getItem in this (simplified) class:

export class Post {
    constructor(){
        this.token = false;
    }

    post() {
        console.log('Token: ' + this.token);
        ...
    }

    setToken(token){
        console.log('Set token.');
        this.token = token;
    }

    authorizedPost() {
        getItem('token', this.setToken.bind(this)).then(
            this.post()
        );
    }
}

I use this class like this:

let post = new Post();
post.authorizedPost();

This is the output I get:

Token: false
Set token.

But I need the token to be set and after that, I want to call the method this.post();

Since I'm a beginner, I want to excuse if that issue is trivial. But I am thankful for every help!

Upvotes: 2

Views: 1776

Answers (2)

Mark
Mark

Reputation: 92440

I know you didn't really ask, but…

Part of the reason the code is difficult to debug is because you are using callbacks when you don't need to and mixing them with promises. These are two different async paradigms that are normally better off separate. You can get rid of the callback in your code in a way that will make it much more readable.

 Expo.SecureStore.getItemAsync()

returns a promise, so just return it.

const getItem = (key) => Expo.SecureStore.getItemAsync(key);

Then in your method you can call then and simply call the function you were passing as a callback. No need for callback or bind. Just one line after the other:

authorizedPost() {
  getItem('token').then(val => {
    this.setToken(val)           // the order is now obvious
    this.post()
  })
  .catch((error) => console.log(error))
}

Here's a snippet with a faked Expo method:

let Expo = {
  SecureStore: {
    getItemAsync() {
      return new Promise((resolve, reject) => setTimeout(() => resolve("someFancyToken"), 1000))
    }
  }
}

class Post {
  constructor() {
    this.token = false;
  }
  post() {
    console.log('Token: ' + this.token);
  }
  setToken(token) {
    console.log('Set token.');
    this.token = token;
  }
  authorizedPost() {
    getItem('token').then(val => {
        this.setToken(val)
        this.post()
      })
      .catch((error) => console.log(error))
  }
}

const getItem = (key) => Expo.SecureStore.getItemAsync(key);

let post = new Post();
post.authorizedPost();

Upvotes: 1

pete
pete

Reputation: 359

I had to pass a function to then like this:

authorizedPost() {
        getItem('token', this.setToken.bind(this)).then(
            ()=>this.post()
        );
    }

Upvotes: 2

Related Questions