承诺不能按预期工作

时间:2018-04-10 09:28:44

标签: javascript promise async-await generator

我想用promise和async / await创建串行动作。代码如下。而不是输出:1 2,我有时得到2 1。有人知道,怎么修理我的问题?只有承诺才有可能吗?用发电机?也可能是onResolve()函数异步工作,所以我也需要让它们同步。

序列:

request.get(payload, onResolve, onReject) //首先获得

.get(payload, onResolve, onReject) //第二次获取

运行first get()执行有效负载(_doSomething(payload)),启动后onResolve()onReject取决于_doSomething()结果,onResolve()之后onReject()启动second get()并执行与第一个get()相同的操作。

class Queue {
  constructor() {
    this.data = [];
  }

  add(record) {
    this.data.unshift(record);
  }

  remove() {
    return this.data.pop();
  }

  isEmpty() {
    return this.data.length === 0;
  }
}

class Request {
  constructor() {
    this._queue = new Queue();
    this._isPending = false;
  }

  _doSomething(payload) {
    setTimeout(() => {
      console.log(payload);
    }, Math.random() * 1000);
  }

  async _runCycle() {
    if (this._queue.isEmpty() || this._isPending) return;

    this._isPending = true;
    
    const { urlOne, onResolve, onReject } = this._queue.remove();
    await Promise.resolve(this._doSomething(urlOne))
      .then(() => onResolve())
      .catch(() => onReject());

    this._isPending = false;
    this._runCycle();
  }

  get(urlOne, onResolve, onReject) {
    
    this._queue.add({ urlOne, onResolve, onReject });
    this._runCycle();

    return this;
  }
}

const request = new Request();

request
  .get('1', ()=>1, ()=>0)
  .get('2', ()=>2, ()=>0);

1 个答案:

答案 0 :(得分:1)

您可以使用单个Promise链,但如果您当前的代码不使用Promise,请重新考虑是否有必要。



class Request {
  constructor() {
    this.resolver = Promise.resolve()
  }

  foo(x,time) {
    return new Promise((res,rej)=>
      setTimeout(() => {
        console.log(x);
        if(x==1)res();
        else rej();
      }, time));
  }

  get(x, time, res, rej) {
    let req = ()=>this.foo(x,time)
    this.resolver = this.resolver.then(req,req).then(res,rej)
    return this;
  }
}

const request = new Request();

request
  .get('1', 1000, ()=>console.log(11), ()=>console.log(10))
  .get('2', 200, ()=>console.log(21), ()=>console.log(20))