在`.then`处理程序中消除不必要的包装函数?

在处理使用Node.js和Bluebird.js的某些项目时,经常会看到以下方法:

function someAsyncOp(arg) { return somethingAsync(arg).then(function (results) { return somethingElseAsync(results); }); } 

这是围绕另一个接受完全相同的参数的函数创build一个包装函数/闭包。 看来这可以写得更干净,如下所示:

 function someAsyncOp(arg) { return somethingAsync(arg).then(somethingElseAsync); } 

当我向其他人提出这个build议时,他们通常会喜欢它,并转向它。

然而,有一个重要的警告:如果你调用的东西像object.function ,而且函数依赖于this (如console.log ),那么this将失去它的绑定。 你必须做object.function.bind(object)

  return somethingAsync(arg).then(somethingElseAsync).catch(console.log.bind(console)); 

这看起来似乎是不可取的,而.bind调用感觉有点尴尬。 你永远不要错过这个永不closures的方法。

我似乎无法在google上find任何关于此的讨论,在ESLint中似乎没有关于不必要的包装函数的任何内容。 我试图find更多关于它,所以我在这里。 我想这是一个我不知道我不知道的情况。 有没有这个名字? (无用的closures?) 任何其他的想法或智慧? 谢谢。

编辑 :有人会评论someAsyncOp也是多余的,是的,让我们假装它做一些有用的事情。

这里的讨论非常简单。 如果你的函数可以被promise系统直接调用,那么当promise系统直接调用它的确切的参数和this值,并且它的返回值正是你在promise链中所需要的,那么所有的意味着,直接指定函数引用作为.then()处理程序:

 somethingAsync(arg).then(somethingElseAsync) 

但是,如果你的函数没有被设置为直接调用,那么你需要一个包装函数或类似.bind()来解决不匹配问题,并根据需要调用你的函数,或设置正确的返回值。

没有比这更多的东西了。 这与在Javascript中的任何地方指定任何callback没有什么不同。 如果您的函数已经完全符合callback的规格,那么您可以将函数名称指定为不带包装的直接引用。 但是,如果你所使用的函数没有像callback函数那样工作,那么你可以使用包装函数来平滑不匹配。

所有的callback函数与传递obj.methodcallback函数都有相同的问题。 如果.method期望this值是obj ,那么你可能不得不做一些事情来确保在你的函数执行之前, this值是相应地设置的。 .then()处理程序中的callback函数与任何其他Javascript / node.js函数(如setTimeout()fs.readFile()或另一个将callback函数作为参数的其他函数的callback函数没有区别。 所以,你所提到的问题都不是承诺所特有的。 它只是发生,承诺通过callback生活,所以如果你想通过callback进行方法调用,你会遇到问题的对象值得到适当的传递给方法。

仅供参考,可以编写方法,使它们永久绑定到自己的对象,并可以作为obj.method传递,但只能在您的方法实现中使用,并有其他一些折衷。 一般来说,有经验的Javascript开发人员完全可以使用obj.method.bind(obj)作为参考。 在代码中看到.bind()也表明你知道你需要在方法内部有正确的obj值,并且已经为此做了一个规定。

至于你的一些粗体问题或评论:

有没有这个名字?

不是我所知道的。 从技术上讲,它是“传递一个以前定义的函数作为callback的名称引用”,但我怀疑这是你可以search和find有用的讨论。

任何其他的想法或智慧?

出于某些原因,我并不完全确定(虽然一直是其他地方讨论的话题),JavaScript编程风格约定似乎鼓励使用匿名内联callback,而不是在其他地方定义方法或函数,然后传递该名称引用(如你会更有可能在许多其他语言)。 很明显,如果你把实际的代码放在一个内联匿名函数中来处理callback,那么你提到的问题都不会出现。 现在使用ES6中的箭头function甚至可以让你保留内联callback中的当前值。 我并不是说这是对你的问题的一个回答,而只是对于常见的Javascript编码习惯的一个观察。

你永远不要错过这个永不closures的方法。

正如你似乎已经知道,如果不需要包装的话,包装一些东西是很浪费的。 只有在callback规范和已经存在的已命名函数之间存在不匹配的情况下,我才会为包装投票,并且有一个原因不能修复命名的函数来匹配callback的规范。