Gaurav Chaudhary
Gaurav Chaudhary

Reputation: 1501

multiple promises inside promise

I wanted to make then chain but my promise was getting resolved before the inner promise execution. How can I fix this?

This code is working fine but I want to make it linear promises chain

functiontest(abc):Promise<any> {

return new Promise((resolve, reject) => {
     this.nativeStorage.getItem('test')
    .then(test => {
            if(test == 1) {
                this.function2(abc).then(tagId=>{
                    this.function3(tagId).then(data=>{
                        resolve(data)
                    });
                });
            }else {
                this.function3(abc).then(data=>{
                    resolve(data)
                });
            }         
        },
        error => {
            this.function2(abc).then(tagId=>{
                this.function3(tagId).then(data=>{
                    resolve(data)
                });
            });       
        }
    )      
});  }

function3 uses the results of function2 only if function2 is called otherwise function3 is called directly

Upvotes: 0

Views: 2899

Answers (3)

HMR
HMR

Reputation: 39260

Because you seem to be stuck I think you may want to think about what the control flow of your application should be because it currently doesn't make much sense when looking at your code and then at your comments. Then test it with mocks and then test it with real functions.

Here is the simplified functionTest function that does what your code does (impossible to do what you want in the comments because that conflicts with what your code actually does). With mock thisObject (you could set thisObject with actual this when you got the control flow right).

const later = value => 
  new Promise(
    (resolve,reject)=>
      setTimeout(
        _=>resolve(value),
        1000
      )
  )
const thisObject = {
  getItem : item => {
    if(item===-1){
      const p = Promise.reject("nope");
      p.catch(ignore=>ignore);//stops the console from shouting
      console.log("in getItem, rejecting with 'nope'");
      return later(p);//return rejected promise without rejection handled
    }
    console.log("in getItem resolving to:"+item);
    return later(item);
  },
  function2 : item => {
    console.log("in function2 with argument:",item);
    return later("function2")
  },
  function3 : item => {
    console.log("in function 3 with argument:",item);
    return later("function3-"+item)
  }
}
const functionTest = abc => {
  //thisObject=this
  return thisObject.getItem(abc)
  .then(//if getItem succeeds
    test =>
      //call fn2 or fn3 with abc (do not pass getitem result to the functions)
      //  depending on getItem result
      (test == 1)
        ? thisObject.function2(abc)//1: call function2 with abc
        : thisObject.function3(abc),//not 1: cll function3 with abc
    error =>//if getItem fails
      //call function2 with abc and function3 with result of function2
      thisObject.function2(abc)
      .then(
        tagId =>
          thisObject.function3(tagId)
      )
  );
}
document.querySelectorAll("input").forEach(
  (el,index)=>el.addEventListener(
    "click",
    e=>
      functionTest(index-1)
      .then(
        result=>console.log("finished, result is:",result)
      )
  )
);
<input type="button" value="getItem that rejects">
<input type="button" value="getItem that resolves to 0">
<input type="button" value="getItem that resolves to 1">

Upvotes: 1

str
str

Reputation: 44969

Your code is really too complicated for what it is actually doing. There is no need to use new Promise when you already get one from getItem and you should avoid the nesting of promise handlers like .then(...then(....then())).

The following code should be functionally equivalent to yours:

function test(abc): Promise<any> {
  return this.nativeStorage.getItem('test')
    .then(test => {
      if (test == 1) {
        return this.function2(abc);
      }
      return abc;
    })
    .catch(() => this.function2(abc))
    .then(tagId => this.function3(tagId));
}

You might also want to look into async/await as a way to implement asynchronous functionality in an easier manner.

Upvotes: 4

Titian Cernicova-Dragomir
Titian Cernicova-Dragomir

Reputation: 249576

Since you are using typescript the best way to make this code more readable is to use async/await:

class testclass {
    // Dummy declaration so the code compiles
    function2: (abc: any) => Promise<string>;
    function3: (abc: any) => Promise<string>;
    nativeStorage: {
        getItem: (p: string) => Promise<number>;
    }
    async test(abc): Promise<any> {
        try {
            let test = await this.nativeStorage.getItem('test')
            if (test == 1) {
                let tagId = this.function2(abc);
                return await this.function3(abc);
            } else {
                return await this.function3(abc)
            }
        }
        catch {
            let tagId = await this.function2(abc)
            return await this.function3(abc)
        }
    }
}

Upvotes: 2

Related Questions