我有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 未定义。 在这两种情况下,我都不传递单参数函数吗?有什么区别?
答案 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
});
}