使用Node的`response.end`方法和promise

0x8*_*890 4 javascript http node.js promise ecmascript-6

假设我有一个基本的HTTP服务器,用"foo"响应所有内容:

import http from 'http'

http.createServer((request, response) =>
  Promise.resolve('foo\n').then(s => response.end(s))
).listen(8888)
Run Code Online (Sandbox Code Playgroud)

这有效,但当我将.then行更改为更短的版本时:

Promise.resolve('foo\n').then(response.end)
Run Code Online (Sandbox Code Playgroud)

它并没有结束回应.我必须遗漏一些非常愚蠢的东西但却想不到它是什么.

the*_*eye 7

end函数必须绑定到该response对象.你可以这样明确地做到这Function.prototype.bind一点

Promise.resolve('foo\n').then(response.end.bind(response))
Run Code Online (Sandbox Code Playgroud)

传递response.endthen函数时,实际上是将函数对象传递给then函数.函数和response对象之间的实际绑定被破坏.例如,在end函数内部,如果它们引用了response对象this,它将不会存在,因为我们已经破坏了它.这就是我们必须将函数对象与实际对象显式绑定的原因.

例如,

function Test(name) {
    this.name = name;
}

Test.prototype.printName = function () {
    console.log(this.name);
}

var test = new Test("thefourtheye");
test.printName();
Run Code Online (Sandbox Code Playgroud)

将打印thefourtheye.但是,如果我们做这样的事情

(function (func) {
    func();
}(test.printName));
Run Code Online (Sandbox Code Playgroud)

它会打印出来undefined.因为test.printName实际上是函数对象,它不会有任何引用test.因此,当调用它时func(),this内部printName将引用全局对象,该对象不会name在其中定义属性.如果我们像这样绑定它

(function (func) {
    func();
}(test.printName.bind(test)));
Run Code Online (Sandbox Code Playgroud)

test.printName.bind将返回一个新函数,它将实际调用test.printName上下文设置为test.这就是为什么它有效.