Giter Site home page Giter Site logo

fe-interview's Introduction

fe-interview's People

Contributors

geekhyt avatar

Stargazers

 avatar  avatar  avatar

Watchers

 avatar

fe-interview's Issues

2.手写 Generator 和 async/await

Generator

// 简易版
function webCanteenGenerator(list) {
    var index = 0;
    var len = list.length;
    return {
      next: function() {
            var done = index >= len;
            var value = !done ? list[index++] : undefined; 
            return {
                done: done,
                value: value
            }
        }
    }
}

async/await

function asyncToGenerator(generatorFn) {
    return function() {
        var gen = generatorFn.apply(this, arguments);
        return new Promise(function(resolve, reject) {
            function step(key, arg) {
                try {
                    var info = gen[key](arg);
                    var value = info.value;
                } catch (error) {
                    reject(error);
                    return;
                }

                if (info.done) {
                    resolve(value);
                } else {
                    return Promise.resolve(value).then(function(value) {
                        step('next', value);
                    }, function(err) {
                        step('throw', err);
                    });
                }
            }
            return step('next');
        });
    }
}

1.手写 Promise 全家桶

想要了解测试方法及代码讲解请稍移玉步到我的这篇专栏

Promise

var PENDING = 'pending';
var FULFILLED = 'fulfilled';
var REJECTED = 'rejected';

function Promise(execute) {
    var that = this;
    that.state = PENDING;
    that.onFulfilledFn = [];
    that.onRejectedFn = [];

    function resolve(value) {
       if (value instanceof Promise) {
            return value.then(resolve, reject)
        }
        setTimeout(function() {
            if (that.state === PENDING) {
                that.state = FULFILLED;
                that.value = value;
                that.onFulfilledFn.forEach(function(f) {
                    f(that.value);
                });
            }
        });
    }

    function reject(reason) {
        setTimeout(function() {
            if (that.state === PENDING) {
                that.state = REJECTED;
                that.reason = reason;
                that.onRejectedFn.forEach(function(f) {
                    f(that.reason);
                });
            }
        });
    }
    try {
        execute(resolve, reject);
    } catch (e) {
        reject(e);
    }
}
Promise.prototype.then = function(onFulfilled, onRejected) {
    onFulfilled =
        typeof onFulfilled === 'function'
            ? onFulfilled
            : function(x) {
                  return x;
              };
    onRejected =
        typeof onRejected === 'function'
            ? onRejected
            : function(e) {
                  throw e;
              };
    var that = this;
    var promise;
    if (that.state === FULFILLED) {
        promise = new Promise(function(resolve, reject) {
            setTimeout(function() {
                try {
                    var x = onFulfilled(that.value);
                    resolvePromise(promise, x, resolve, reject);
                } catch (reason) {
                    reject(reason);
                }
            });
        });
    }
    if (that.state === REJECTED) {
        promise = new Promise(function(resolve, reject) {
            setTimeout(function() {
                try {
                    var x = onRejected(that.reason);
                    resolvePromise(promise, x, resolve, reject);
                } catch (reason) {
                    reject(reason);
                }
            });
        });
    }
    if (that.state === PENDING) {
        promise = new Promise(function(resolve, reject) {
            that.onFulfilledFn.push(function() {
                try {
                    var x = onFulfilled(that.value);
                    resolvePromise(promise, x, resolve, reject);
                } catch (reason) {
                    reject(reason);
                }
            });
            that.onRejectedFn.push(function() {
                try {
                    var x = onRejected(that.reason);
                    resolvePromise(promise, x, resolve, reject);
                } catch (reason) {
                    reject(reason);
                }
            });
        });
    }
    return promise;
};

function resolvePromise(promise, x, resolve, reject) {
    if (promise === x) {
        return reject(new TypeError('x 不能与 promise 相等'));
    }
    if (x instanceof Promise) {
        if (x.state === FULFILLED) {
            resolve(x.value);
        } else if (x.state === REJECTED) {
            reject(x.reason);
        } else {
            x.then(function(y) {
                resolvePromise(promise, y, resolve, reject);
            }, reject);
        }
    } else if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
        var executed;
        try {
            var then = x.then;
            if (typeof then === 'function') {
                then.call(
                    x,
                    function(y) {
                        if (executed) return;
                        executed = true;
                        resolvePromise(promise, y, resolve, reject);
                    },
                    function(e) {
                        if (executed) return;
                        executed = true;
                        reject(e);
                    }
                );
            } else {
                resolve(x);
            }
        } catch (e) {
            if (executed) return;
            executed = true;
            reject(e);
        }
    } else {
        resolve(x);
    }
}

module.exports = {
    deferred() {
        var resolve;
        var reject;
        var promise = new Promise(function(res, rej) {
            resolve = res;
            reject = rej;
        });
        return {
            promise,
            resolve,
            reject,
        }
    }
}

Promise.resolve

Promise.resolve = function(value) {
    if (value instanceof Promise) {
        return value;
    }

    return new Promise(function(resolve, reject) {
        resolve(value);
    });
}

Promise.reject

Promise.reject = function(reason) {
    return new Promise(function(resolve, reject) {
        reject(reason);
    });
}

Promise.prototype.catch

Promise.prototype.catch = function(onRejected) {
    return this.then(null, onRejected);
}

Promise.prototype.finally

Promise.prototype.finally = function(fn) {
    return this.then(function(value) {
        return Promise.resolve(fn()).then(function() {
            return value;
        })
    }, function(error) {
        return Promise.resolve(fn()).then(function() {
            throw error;
        });
    });
}

Promise.all

Promise.all = function(promiseArr) {
    return new Promise(function(resolve, reject) {
        const length = promiseArr.length;
        const result = [];
        let count = 0;
        if (length === 0) {
            return resolve(result);
        }

        for (let [i, p] of promiseArr.entries()) {
            Promise.resolve(p).then(function(data) {
                result[i] = data;
                count++;
                if (count === length) {
                    resolve(result);
                }
            }, function(reason) {
                reject(reason);
            });
        }
    });
}

Promise.race

Promise.race = function(promiseArr) {
    return new Promise(function(resolve, reject) {
        const length = promiseArr.length;
        if (length === 0) {
            return resolve();
        } 

        for (let item of promiseArr) {
            Promise.resolve(item).then(function(value) {
                return resolve(value);
            }, function(reason) {
                return reject(reason);
            });
        }
    });
}

Promise.any

Promise.any = function(promiseArr) {
    return new Promise(function(resolve, reject) {
        const length = promiseArr.length;
        const result = [];
        let count = 0;
        if (length === 0) {
            return resolve(result);
        } 

        for (let [i, p] of promiseArr.entries()) {
            Promise.resolve(p).then((value) => {
                return resolve(value);
            }, (reason) => {
                result[i] = reason;
                count++;
                if (count === length) {
                    reject(result);
                }
            });
        }
     });
}

Promise.allSettled

Promise.allSettled = function(promiseArr) {
  return new Promise(function(resolve) {
    const length = promiseArr.length;
    const result = [];
    let count = 0;

    if (length === 0) {
      return resolve(result);
    } else {
      for (let [i, p] of promiseArr.entries()) {
        Promise.resolve(p).then((value) => {
            result[i] = { status: 'fulfilled', value: value };
            count++;
            if (count === length) {
                return resolve(result);
            }
        }, (reason) => {
            result[i] = { status: 'rejected', reason: reason };
            count++;
            if (count === length) {
                return resolve(result);
            }
        });
      }
    }
  });
}

使用 Promise.finally 实现 Promise.allSettled

Promise.allSettled = function(promises) {
    // 也可以使用扩展运算符将 Iterator 转换成数组
    // const promiseArr = [...promises];
    const promiseArr = Array.from(promises);
    return new Promise(resolve => {
        const result = [];
        const len = promiseArr.length;
        let count = len;
        if (len === 0) {
          return resolve(result);
        }
        for (let i = 0; i < len; i++) {
            promiseArr[i].then((value) => {
                result[i] = { status: 'fulfilled', value: value };
            }, (reason) => {
                result[i] = { status: 'rejected', reason: reason };
            }).finally(() => { 
                if (!--count) {
                    resolve(result);
                }
            });
        }
    });
}

使用 Promise.all 实现 Promise.allSettled

Promise.allSettled = function(promises) {
    // 也可以使用扩展运算符将 Iterator 转换成数组
    // const promiseArr = [...promises];
    const promiseArr = Array.from(promises);
    return Promise.all(promiseArr.map(p => Promise.resolve(p).then(res => {
      return { status: 'fulfilled', value: res }
    }, error => {
      return { status: 'rejected', reason: error }
    })));
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.