Promises - 传递解析函数和包装函数之间的区别

时间:2016-12-12 11:53:22

标签: javascript node.js promise

我有Node.js应用程序。为什么这两个代码片段不能以相同的方式工作?

1)

function myFn1() {
    return new Promise(function(resolve, reject) {
        myFn2().then(function(url) {
            resolve(url);
        });
    });
}

2)

function myFn1() {
    return new Promise(function(resolve, reject) {
        myFn2().then(resolve);
    });
}

普通的:

function myFn2() {
    return new Promise(function(resolve, reject) {
        var url = 'example.com';
        resolve(url);
    });
}

我用

打电话
myFn1().then(function(url) {
    console.log(url);
});

使用代码1)正确传递 url ,但代码为2) url 未定义。 在这两种情况下,我都不传递单参数函数吗?有什么区别?

1 个答案:

答案 0 :(得分:2)

首先,避免承诺反模式。当你已经有一个承诺时,只需使用它并返回它。不要将它包装在新的承诺中。除了效率低下之外,很容易出错,尤其是错误处理(你有)。

所以,你应该做的是:

function myFn1() {
    return myFn2().then(function(url) {
        // do some modification to url and then return that
        // or some other processing here
        return url;
    });
}

根本不需要将myFn2()中返回的承诺包装在另一个承诺中。在您这样做的具体情况下,您默默地从该内部承诺中获取任何错误,并且它们不会传播给myFn1()的调用者,这几乎总是一个错误,有时是一个非常严重的错误。

而且,如果你在.then()处理程序中真的无所事事,那么你甚至不需要它:

function myFn1() {
    // some code here
    return myFn2();
}

至于原始问题,你的两个代码片段1)和2)以相同的方式工作,除了一个进行额外的函数调用之外没有任何有意义的行为差异,并且使用更多的堆栈来执行此操作。

执行此操作时:

myFn2().then(resolve);

您告诉.then()使用通常传递给resolve处理程序的任何参数调用.then()。由于您的案例中的参数为url,因此:

.then(resolve);

与:

完全相同
.then(function(url) {
    resolve(url);
});

他们都用完全相同的参数调用resolve。第一个是速记,当.then()将用于它的回调的参数正是你想要的函数的参数时,应该使用它。如果函数的参数不完全相同,或者显然,如果在.then()处理程序中有多个函数调用,则应使用第二个。因此,如果您想在调用resolve之前向URL添加".jpg"扩展名,那么您必须这样做:

.then(function(url) {
    resolve(url + ".jpg");
});
  

使用代码1)url正确传递,但代码为2)url是   未定义。在这两种情况下,我都不传递单参数函数吗?什么是   区别?

假设myFn2()返回的承诺解析为url,那么您的方案#1和#2之间应该没有区别。 myFn1()返回的承诺应该以任何方式解析为相同的值。

现在,如果您在.then()处理程序中放入一些代码并忘记从该.then()处理程序返回所需的值,那么该承诺的已解析值将变为undefined,这可能是真实代码中发生了什么。所以,如果你这样做:

function myFn1() {
    return myFn2().then(function(url) {
        console.log(url);
    });
}

myFn1().then(function(url) {
    console.log(url);     // will be undefined
})

因为您没有从.then()内的myFn1处理程序返回任何内容。这意味着返回值为undefined,因此承诺采用了返回值。请记住,如果您希望您的承诺具有特定的已解决值,则必须从链中的任何.then()处理程序返回它。

function myFn1() {
    return myFn2().then(function(url) {
        console.log(url);
        return url;            // make sure the promise retains this resolved value
    });
}