Javascript 承诺-传递解析函数和包装函数之间的差异
我有Node.js应用程序。为什么这两个代码片段的工作方式不同 (一) (二) 常见的: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
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
还有更多内容。