Javascript Promisification,为什么要使用“调用”?

Javascript Promisification, why use "call"?

提问人:Elbasel 提问时间:7/24/2022 最后编辑:Elbasel 更新时间:7/24/2022 访问量:84

问:

我想了解为什么在下面的示例中使用了“call”方法。

loadScript是一个将脚本标记附加到文档的函数,并具有可选的回调函数。

promisify返回一个包装函数,该包装函数又返回一个 promise,有效地将“loadScript”从基于回调的函数转换为基于 promise 的函数。

function promisify(f) {
  return function (...args) { // return a wrapper-function 
    return new Promise((resolve, reject) => {
      function callback(err, result) { // our custom callback for f 
        if (err) {
          reject(err);
        } else {
          resolve(result);
        }
      }

      args.push(callback); // append our custom callback to the end of f arguments

      f.call(this, ...args); // call the original function
    });
  };
}

// usage:
let loadScriptPromise = promisify(loadScript);
loadScriptPromise(...).then(...);

loadScript():

function loadScript(src, callback) {
  let script = document.createElement("script");
  script.src = src;

  script.onload = () => callback(null, script);
  script.onerror = () => callback(new Error(`Script load error for ${src}`));

  document.head.append(script);
}

我知道这是用于在函数调用期间强制某个上下文的,但为什么不使用 just use 而不是 ?callf(...args)f.call(this, ...args)

javascript 回调 es6-promise

评论

5赞 VLAZ 7/24/2022
"f(...args) 而不是 f.call(this, ...args)?因为 的值不会被保留。this
0赞 Elbasel 7/24/2022
是的,但是为什么我们需要在这种特殊情况下保留价值呢?this
4赞 T.J. Crowder 7/24/2022
@Elbasel - 因为是一个通用函数,你可以在方法上使用它。promisify
0赞 T.J. Crowder 7/24/2022
stackoverflow.com/questions/20279484/ 的副本...
1赞 Pointy 7/24/2022
@T.J.Crowder:我认为这基本上是重复的,但这是一个有趣的极端情况。

答:

1赞 2 revsT.J. Crowder #1

promisify是一个通用函数。当然,你不关心 ,但如果你在 on 上使用方法,你会关心的。所以这有效:thisloadScriptpromisify

function promisify(f) {
  return function (...args) { // return a wrapper-function 
    return new Promise((resolve, reject) => {
      function callback(err, result) { // our custom callback for f 
        if (err) {
          reject(err);
        } else {
          resolve(result);
        }
      }

      args.push(callback); // append our custom callback to the end of f arguments

      f.call(this, ...args); // call the original function
    });
  };
}

class Example {
    constructor(a) {
        this.a = a;
    }
    method(b, callback) {
        const result = this.a + b;
        setTimeout(() => callback(null, result), 100);
    }
}

(async () => {
    try {
        const e = new Example(40);
        const promisifiedMethod = promisify(e.method);
        const result = await promisifiedMethod.call(e, 2);
        console.log(result);
    } catch (error) {
        console.error(error);
    }
})();

如果不使用它返回的函数接收的函数,那将不起作用:promisifythis

function promisifyNoCall(f) {
  return function (...args) { // return a wrapper-function 
    return new Promise((resolve, reject) => {
      function callback(err, result) { // our custom callback for f 
        if (err) {
          reject(err);
        } else {
          resolve(result);
        }
      }

      args.push(callback); // append our custom callback to the end of f arguments

      f(...args); // call the original function *** changed
    });
  };
}

class Example {
    constructor(a) {
        this.a = a;
    }
    method(b, callback) {
        const result = this.a + b;
        setTimeout(() => callback(null, result), 100);
    }
}

(async () => {
    try {
        const e = new Example(40);
        const promisifiedMethod = promisifyNoCall(e.method);
        const result = await promisifiedMethod.call(e, 2);
        console.log(result);
    } catch (error) {
        console.error(error);
    }
})();

评论

0赞 Elbasel 7/24/2022
谢谢,这是一个非常详细的答案。我可以打扰您一些参考资料,以帮助我了解您对 and 的用法吗?thiscall
0赞 T.J. Crowder 7/24/2022
@Elbasel - MDN 是一个很好的资源:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...还有这个问题的答案这个问题。祝您编码愉快!