Javascript 承诺-传递解析函数和包装函数之间的差异

Javascript 承诺-传递解析函数和包装函数之间的差异,javascript,node.js,promise,Javascript,Node.js,Promise,我有Node.js应用程序。为什么这两个代码片段的工作方式不同 (一) (二) 常见的: function myFn2() { return new Promise(function(resolve, reject) { var url = 'example.com'; resolve(url); }); } 我称之为 myFn1().then(function(url) { console.log(url); }); 对于代码1)ur

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

(一)

(二)

常见的:

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未定义。
我不是在两种情况下都传递一个参数函数吗?区别是什么?

首先,避免使用承诺反模式。当你已经有了一个承诺,就使用它并回报它。不要用新的承诺来包装它。除了效率低下之外,还很容易犯错误,特别是在错误处理方面(你已经做到了)

所以,你应该做的是:

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()
的调用方,这几乎总是一个bug,有时是一个非常严重的bug

而且,如果您在
.then()
处理程序中确实无事可做,那么您甚至不需要它:

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

至于最初的问题,您的两个代码片段(1)和(2)的工作方式相同,没有任何有意义的行为差异,只有一个代码片段进行了额外的函数调用,并使用了更多的堆栈

执行此操作时:

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

myFn1().then(function(url) {
    console.log(url);     // will be undefined
})
您告诉
.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()
处理程序返回所需的值,那么承诺的解析值将变为
未定义的
,这可能是实际代码中发生的情况。因此,如果您这样做:

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

myFn1().then(function(url) {
    console.log(url);     // will be undefined
})
因为您没有从
myFn1
中的
.then()
处理程序返回任何内容。这意味着返回值
未定义
,因此承诺接受该返回值。请记住,如果希望承诺具有特定的解析值,则必须从链中的任何
.then()
处理程序返回它

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

如果我修正了输入错误(在
函数()myFn2
函数之后的
()
),这两种方法都适用于我(它们应该如此):我使用“code 1”作为
myFn1A
和“code 2”作为
myFn1B
…但是,当然,你不会希望
myFn1
在任何情况下都能这样做。它创造了一个不必要的新承诺。您可能需要
function myFn1(){return myFn2()。然后(function(url){/*大概做点什么,然后:*/return url;});}
或类似的方法。
myFn2()。然后(resolve)不应该是
myFn2()。然后(url=>resolve(url))
使用一个参数函数意味着什么?@AshwaniAgarwal:如果
使用一个参数调用它的回调函数,那么您在那里的两个调用会做完全相同的事情(只是中间有一个额外的不必要的函数)。请注意,或者更简短地说,
const myFn1=myFn2
@torazaburo-这里的假设是,除了调用
myFn2
之外,
myFn1
还有更多内容。