admin管理员组

文章数量:1025557

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

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

Share Improve this question edited Feb 1, 2018 at 16:45 Gaurav Chaudhary asked Feb 1, 2018 at 15:54 Gaurav ChaudharyGaurav Chaudhary 1,50115 silver badges28 bronze badges 3
  • 2 It's a "callback hell" all over again. – palaѕн Commented Feb 1, 2018 at 15:56
  • @palaѕн right. That's what I am trying to avoid because that is the motive of promises – Gaurav Chaudhary Commented Feb 1, 2018 at 15:57
  • function3 uses the results of function2 only if function2 is called otherwise function3 is called directly – Gaurav Chaudhary Commented Feb 1, 2018 at 16:47
Add a ment  | 

3 Answers 3

Reset to default 4

Your code is really too plicated 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.

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

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 ments. 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 ments 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">

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

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

Share Improve this question edited Feb 1, 2018 at 16:45 Gaurav Chaudhary asked Feb 1, 2018 at 15:54 Gaurav ChaudharyGaurav Chaudhary 1,50115 silver badges28 bronze badges 3
  • 2 It's a "callback hell" all over again. – palaѕн Commented Feb 1, 2018 at 15:56
  • @palaѕн right. That's what I am trying to avoid because that is the motive of promises – Gaurav Chaudhary Commented Feb 1, 2018 at 15:57
  • function3 uses the results of function2 only if function2 is called otherwise function3 is called directly – Gaurav Chaudhary Commented Feb 1, 2018 at 16:47
Add a ment  | 

3 Answers 3

Reset to default 4

Your code is really too plicated 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.

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

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 ments. 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 ments 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">

本文标签: javascriptmultiple promises inside promiseStack Overflow