简单的承诺然后实现

时间:2019-04-05 11:08:46

标签: javascript promise

最近向我展示了一段代码,这些代码是在全栈开发人员访谈中被要求的。 它涉及创建一个Promise,候选人应在其中执行, 向其传递一个resolve函数,然后链接2个。

我试图非常天真地实现Promise只是为了使代码正常工作。 创建了一个接受解析器功能的ctor, 创建了一个then函数,该函数接受回调并返回Promise, 并只需在resolver函数上调用回调。

class MyPromise {

    constructor(resolver) {
        this.resolver = resolver;
    }

    then(callback) {
        const result = new MyPromise(callback);
        this.resolver(callback);

        return result;
    }
}

promise = new MyPromise(
    (result) => {
        setTimeout(result(2), 500);
    });
promise.then(result => {
    console.log(result);
    return 2 * result;
}).then(result => console.log(result));

预期结果为2,4-就像在真正的Promise上运行一样。 但是我得到了2,2。 我在弄清楚如何获取第一个“ then”的返回值并将其传递时遇到麻烦。

5 个答案:

答案 0 :(得分:3)

这是创建诺言类的简化代码,

class MyPromise {
  constructor(executor) {
    this.callbacks = [];

    const resolve = res => {
      for (const { callback } of this.callbacks) {
        callback(res);
      }
    };

    executor(resolve);
  }

  then(callback) {
    return new MyPromise((resolve) => {
      const done = res => {
        resolve(callback(res));
      };
      this.callbacks.push({ callback: done });
    });
  }
}


promise = new MyPromise((resolve) => {
  setTimeout(() => resolve(2), 1000);
});

promise.then(result => {
  console.log(result);
  return 2 * result;
}).then(result => console.log(result));

答案 1 :(得分:2)

您的问题有一些问题:

  • r2变量未定义。我会假设使用result
  • setTimeout无济于事,因为您立即执行result(2)。我会假设使用setTimeout(() => result(2), 500)

如果在采访中确实给出了这样的代码,那么在做其他事情之前指出这两个问题将是您的工作。

您尝试进行操作时遇到的一个问题是,then方法(即result)返回的承诺从未得到解决。您需要尽快解决this承诺,并使用then回调返回的值来解决它。

此外,promise构造函数参数是一个应立即执行的函数。

在以下解决方案中,与正确的Promise行为相比,进行了一些简化。

  • 它不会异步调用then回调;
  • 它不支持在同一诺言上进行多个then呼叫;
  • 它不提供拒绝路径;
  • 这不会阻止一个承诺以不同的价值解决两次;
  • 它不处理then回调返回诺言的特殊情况

console.log("Wait for it...");

class MyPromise {
    constructor(executor) {
        executor(result => this.resolve(result));
    }
    resolve(value) {
        this.value = value;
        this.broadcast();
    }
    then(onFulfilled) {
        const promise = new MyPromise(() => null);
        this.onFulfilled = onFulfilled;
        this.resolver = (result) => promise.resolve(result);
        this.broadcast();
        return promise;
    }
    broadcast() {
        if (this.onFulfilled && "value" in this) this.resolver(this.onFulfilled(this.value)); 
    }
};

// Code provided by interviewer, including two corrections
promise = new MyPromise(
    (result) => {
        setTimeout(()=>result(2), 500); // don't execute result(2) immediately
    });
promise.then(result => {
    console.log(result); // Changed r2 to result.
    return 2 * result;
}).then(result => console.log(result));

请注意输出中有500ms的延迟,这是(更正的)setTimeout代码所期望的。

我在this answer

中发布了完整的符合Promises / A +的Promise实现并带有注释

答案 2 :(得分:2)

那很简单:

const SimplePromise = function(cb) {
  cb(
    data =>
      (this.data = data) &&
      (this.thenCb || []).forEach(chain => (this.data = chain(this.data))),
    error =>
      (this.error = error) &&
      (this.catchCb || []).forEach(chain => (this.error = chain(this.error)))
  );
  this.then = thenCb =>
    (this.thenCb = [...(this.thenCb || []), thenCb]) && this;
  this.catch = catchCb =>
    (this.catchCb = [...(this.catchCb || []), catchCb]) && this;
};

此处的示例:https://codesandbox.io/s/0q1qr8mpxn

答案 3 :(得分:0)

暗示此r2实际上是结果参数。 代码的问题是您不从result(2)中检索结果。执行第一个“ then”,打印2,返回4,但是这4被浪费了。 我编写了一些具有同步功能的代码,只是为了演示如何获取此2,4输出:

class MyPromise {
    constructor(resolver) {
        this.resolver = resolver;
    }

    then(callback) {
          var res = callback(this.resolver());
        var result = new MyPromise(() => { return res; });

        return result;
    }
}

let promise = new MyPromise(
    () => {
        return 2;
    });

promise
.then(result => {
    console.log(result);
    return 2 * result;
})
.then(result => {
        console.log(result);
});

如果希望解析器稍微异步,则应使用Promises(因为可以检索在setTimeout内部执行的函数的返回值,请参见 here

如果不允许您使用这些内置的Promises,则可以自己编写一些虚拟的延迟对象,然后等待它们(setInterval)进行解析(基本上是相同的逻辑)。

答案 4 :(得分:0)

您的原始代码存在一些问题。值得注意的是,您仅在调用then方法时执行构造函数参数,而实际上并没有链接'then'回调的输出。

这是基于调整您的示例的非常(非常!)基本promise实现。它也适用于在解决承诺后调用“ then”的情况(但如果已经调用了“ then”,则不适用-不支持多个then块)。

class MyPromise {
    constructor(resolver) {
        let thisPromise = this;

        let resolveFn = function(value){
            thisPromise.value = value; 
            thisPromise.resolved = true;
            if(typeof thisPromise.thenResolve === "function"){
                thisPromise.thenResolve();
            }
            
        }
        if (typeof resolver === "function") {
            resolver(resolveFn);
        }
    }
    then(callback) {
        let thisPromise = this;
        thisPromise.thenFn = callback;

        return new MyPromise((resolve) =>{
            thisPromise.thenResolve = () => {
                thisPromise.value = thisPromise.thenFn(thisPromise.value);
                resolve(thisPromise.value);
            }
            //automatically resolve our intermediary promise if 
            //the parent promise is already resolved
            if(thisPromise.resolved){
                thisPromise.thenResolve();
            }
        });

        
    }
};

//test code

console.log("Waiting for Godot...");

promise = new MyPromise((resolve) =>{
    setTimeout(()=>{
        resolve(2)
    },500);
});


promise.then((result) => {
    console.log(result);
    return 2 * result;
}).then((result) => {
    console.log(result);
    return 2 * result;
}).then((result) => {
    console.log(result)
});