Javascript:抛出异步链接方法

时间:2018-06-14 22:42:24

标签: javascript promise async-await

我有一个类,它返回了几个像这样被链接的方法:

class MyClass{
  foo(){
    if(condition) return this;
    else throw;
  }

  bar(){
    if(condition) return this;
    else throw;
  }
}

条件是某些检查可能是真或假,具体取决于类的内部状态

我的想法是我可以执行以下几种方法:

myInstance.foo().bar();

这样,如果任何方法中的任何条件都失败,则此语句将引发错误。

但是,现在我试图检查需要解决的承诺的条件:

class MyClass2{
  asynCheck(){
     myPromise.then((condition)=>{
        ... // returning a promise won't work
     });

我想保持与以前相同的语法(添加await / then),我不介意改变foo和bar也是异步,只要以下语法有效:

await myInstance.foo().asyncCheck().bar();

有没有办法做到这一点?请注意,可能有多个asyncCheck,可以按任何顺序调用

3 个答案:

答案 0 :(得分:1)

你可以用一些主要的黑客来做这件事......



class MyClass {
  foo() {
    const ret = new Promise((resolve, reject) => {
      resolve(1);
    })
    ret.bar = this.bar.bind(this);
    return ret;
  }

  bar() {
    const ret = new Promise((resolve, reject) => {
      resolve(2);
    })
    // hack `ret` to copy the methods over...
    return ret;
  }
}

(async() => {
  const c = new MyClass;
  console.log(await c.foo())
  console.log(await c.foo().bar())

})()




答案 1 :(得分:0)

您可以使用内部Promise字段实现此目的,并在每次调用方法时重新分配:

class MyClass {
  constructor(promise) {
    if (!promise) this.promise = Promise.resolve();
    else this.promise = promise;
  }
  foo(condition) {
    this.promise = this.promise.then(() => {
        console.log("foo");
        if (!condition) throw 'foo error';
    });
    return this;
  }
  bar(condition) {
    this.promise = this.promise.then(() => {
        console.log("bar");
        if (!condition) throw 'bar error';
    });
    return this;
  }
  asynCheck(conditionPromise) {
    this.promise = this.promise.then(() => {
        return conditionPromise.then(condition => {
          console.log("asynCheck");
          if (!condition) throw 'asynCheck error';
        });
    });
    return this;
  }
  catch(callback) {
    this.promise.catch(callback);
  }
}

let instance = new MyClass();

instance.foo(true)
        .asynCheck(new Promise((res, rej) => setTimeout(() => res(true), 2000)))
        .bar(true)
        .asynCheck(new Promise((res, rej) => setTimeout(() => res(false), 3000)))
        .foo(false)
        .catch(e => console.log(e));

答案 2 :(得分:0)

经过大量测试后,我找到了一个可能的解决方案,用Promise扩展了这个类,结果是这样的:

class MyClass extends Promise {
  constructor(executor){
    super((resolve, reject)=>{return executor(resolve,reject)});
  }
  foo(){
    return new MyClass((resolve, reject)=>{
      this.then(()=>{
        if(condition) resolve();
        else reject();
      }).catch(()=> reject());
    })
  }

  asyncCheck(){
    return new MyClass((resolve, reject)=>{
      this.then(()=>{
         asyncCondition.then((condition)=>{
             if(condition) resolve();
             else reject();
         });
      }).catch(()=> reject());
    })
  }
}
const bar=new MyClass((r)=>{r()});
await bar.foo().asyncCheck();

主要的权衡是构造函数需要一个虚拟回调,因为扩展的promises如何工作。