Skip to content

第 64 题:模拟实现一个 Promise.finally #109

Open
@lvtraveler

Description

@lvtraveler
Promise.prototype.finally = function (callback) {
  let P = this.constructor;
  return this.then(
    value  => P.resolve(callback()).then(() => value),
    reason => P.resolve(callback()).then(() => { throw reason })
  );
};

Activity

xueqingxiao

xueqingxiao commented on Apr 28, 2019

@xueqingxiao
wingmeng

wingmeng commented on Apr 28, 2019

@wingmeng
window.Promise && !('finally' in Promise) && !function() {        
  Promise.prototype.finally = function(cb) {
    cb = typeof cb === 'function' ? cb : function() {};
      
    var Fn = this.constructor;  // 获取当前实例构造函数的引用

    // 接受状态:返回数据
    var onFulfilled = function(data) {
      return Fn.resolve(cb()).then(function() {
        return data
      })
    };

    // 拒绝状态:抛出错误
    var onRejected = function(err) {
      return Fn.resolve(cb()).then(function() {
        throw err
      })
    };

    return this.then(onFulfilled, onRejected);
  }
}();

/*********************** 测试 ***********************/
const p = new Promise((resolve, reject) => {
  console.info('starting...');

  setTimeout(() => {
    Math.random() > 0.5 ? resolve('success') : reject('fail');
  }, 1000);
});

// 正常顺序测试
p.then((data) => {
    console.log(`%c resolve: ${data}`, 'color: green')
  })
  .catch((err) => {
    console.log(`%c catch: ${err}`, 'color: red')
  })
  .finally(() => {
    console.info('finally: completed')
  });

// finally 前置测试  
p.finally(() => {
    console.info('finally: completed')
  })	
  .then((data) => {
    console.log(`%c resolve: ${data}`, 'color: green')
  })
  .catch((err) => {
    console.log(`%c catch: ${err}`, 'color: red')
  });
xbcc123

xbcc123 commented on May 3, 2019

@xbcc123
	window.Promise.prototype = {
			finally: function(callback) {
				let P = this.constructor;
				  return this.then(
				    value  => P.resolve(callback()).then(() => value),
				    reason => P.resolve(callback()).then(() => { throw reason })
				  );
			}
		}

抄了个...

hello-chinese

hello-chinese commented on Jun 12, 2019

@hello-chinese
Promise.prototype.finally = function (callback) {
  let P = this.constructor;
  return this.then(
    value  => {
          callback();
          return value;
     },
    reason => {
        callback();
        throw reason
    }
  );
};

为什么需要Promise.resolve(callback()).then(() => value)
而不能直接执行callback, return value

NathanHan1

NathanHan1 commented on Jul 16, 2019

@NathanHan1
Promise.prototype.finally = function(callback) {
        return this.then(
          () => {
            callback();
          },
          () => {
            callback();
          }
        );
      };
Arrogant128

Arrogant128 commented on Jul 17, 2019

@Arrogant128
Promise.prototype.finally = function(callback){
  const constructor = this.constructor
  return this.then(value => {
    return constructor.resolve(callback()).then(() => value)
  }),
  reason => {
    return constructor.resolve(callback()).then(() => throw reason)
  }
}
HCLQ

HCLQ commented on Jul 19, 2019

@HCLQ
Promise.prototype.finally = function (callback) {
  let P = this.constructor;
  return this.then(
    value  => {
          callback();
          return value;
     },
    reason => {
        callback();
        throw reason
    }
  );
};

为什么需要Promise.resolve(callback()).then(() => value)
而不能直接执行callback, return value

因为callback如果是个异步操作,返回promise呢.希望等callback执行完再接着执行

pagemarks

pagemarks commented on Aug 16, 2019

@pagemarks

https://github.com/taylorhakes/promise-polyfill/blob/master/src/finally.js

finally是一个关键字,在IE低版本会引发解析错误,若兼容IE不能直接object.key语法.

Promise.prototype['finally'] = function (callback) {
  var constructor = this.constructor;
  return this.then(
    function(value) {
      // @ts-ignore
      return constructor.resolve(callback()).then(function() {
        return value;
      });
    },
    function(reason) {
      // @ts-ignore
      return constructor.resolve(callback()).then(function() {
        // @ts-ignore
        return constructor.reject(reason);
      });
    }
  );
}
yft

yft commented on Aug 26, 2019

@yft

看了这个问题才知道,原来 promise 的 finally 只是不管成功还是失败都会执行而已,而不会永远最后执行😂

new Promise((resolve, reject) => {
    resolve();
}).finally(() => {
    console.log('finally1');
}).then(() => {
    console.log('then');
}).finally(() => {
    console.log('finally2');
});
finally1
then
finally2
x-shadow-x

x-shadow-x commented on Sep 25, 2019

@x-shadow-x
Promise.prototype.finally = function (callback) {
  let P = this.constructor;
  return this.then(
    value  => P.resolve(callback()).then(() => value),
    reason => P.resolve(callback()).then(() => { throw reason })
  );
};

想问下,这里先通过P缓存this.constructor,后面再通过P.resolve的方式调用是有什么目的么,为什么不是直接value => Promise.resolve(callback()).then(() => value),reason => Promise.resolve(callback()).then(() => { throw reason })~ 谢谢

nianxiongdi

nianxiongdi commented on Oct 6, 2019

@nianxiongdi

来个简洁版的:

finally(callback) {
    return this.then(
        (res) => {
            callback();
            return res;
        },
        (err) => {
            callback();
            return err;
        }
    );
}
SoftwareEngineerPalace

SoftwareEngineerPalace commented on Oct 14, 2019

@SoftwareEngineerPalace
Promise.prototype.finally = function (callback) {
  let P = this.constructor;
  return this.then(
    value  => P.resolve(callback()).then(() => value),
    reason => P.resolve(callback()).then(() => { throw reason })
  );
};

看一个多月,还是没看懂,哪位大神能逐句解释一下

SoftwareEngineerPalace

SoftwareEngineerPalace commented on Oct 14, 2019

@SoftwareEngineerPalace
Promise.prototype.finally = function (callback) {
  let P = this.constructor;
  return this.then(
    value  => P.resolve(callback()).then(() => value),
    reason => P.resolve(callback()).then(() => { throw reason })
  );
};

想问下,这里先通过P缓存this.constructor,后面再通过P.resolve的方式调用是有什么目的么,为什么不是直接value => Promise.resolve(callback()).then(() => value),reason => Promise.resolve(callback()).then(() => { throw reason })~ 谢谢

同问

liujie2019

liujie2019 commented on Nov 5, 2019

@liujie2019
Promise.prototype.finally = function (callback) {
  let P = this.constructor;
  return this.then(
    value  => P.resolve(callback()).then(() => value),
    reason => P.resolve(callback()).then(() => { throw reason })
  );
};

想问下,这里先通过P缓存this.constructor,后面再通过P.resolve的方式调用是有什么目的么,为什么不是直接value => Promise.resolve(callback()).then(() => value),reason => Promise.resolve(callback()).then(() => { throw reason })~ 谢谢

我觉得是为了兼容那些自定义的Promise版本。比如说可以自己实现一个Promise叫MyPromise,像resolve和reject这些静态方法都是挂载在MyPromise上的。通过这样let P = this.constructor;写,兼容性更好吧。

17 remaining items

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @xueqingxiao@x-shadow-x@SoftwareEngineerPalace@yft@wingmeng

        Issue actions

          第 64 题:模拟实现一个 Promise.finally · Issue #109 · Advanced-Frontend/Daily-Interview-Question