重构 - 检查 promise 之前是否已经解决
Refactoring - Checking if promise has been resolved before
此函数获取外部提供的用户文件列表API。一旦检索到数据,它就会被保存,因此下次调用它时 returns 之前保存的相同数据。此代码在控制器级别。
var userFiles = {};
function getUserFiles(user) {
var dfd = $q.defer();
// Files already have been loaded
if (userFiles[user.id]) {
dfd.resolve(userFiles[user.id]);
} else {
// Get files for the first time
Users.getFiles(user).then(function(files) {
userFiles[user.id] = files;
dfd.resolve(userFiles[user.id]);
});
}
return dfd.promise;
}
您将如何重构此代码以使其仅调用一次 dfd.resolve?
var userFiles = {};
function getUserFiles(user) {
var dfd = $q.defer();
if (!userFiles[user.id]) {
// Get files for the first time
Users.getFiles(user).then(function(files) {
userFiles[user.id] = files;
});
dfd.resolve(userFiles[user.id]);
}
return dfd.promise;
}
编辑 #2
我有一个甚至 更好 的片段给你:
function getUserFiles(user) {
return userFiles[user.id] || (userFiles[user.id] = Users.getFiles(user));
}
这将 userFiles[user.id]
设置为 return 由 Users.getFiles(user)
编辑并 return 的承诺。如果 userFiles[user.id]
已经设置(即它是 truth-y)那么它只是 return 之前解决的承诺。
使用这个超短代码段的缺点是您没有进行任何故障检查 - 并且可能最终缓存失败的请求 - 再一次,您也没有在其他代码中进行任何故障检查。
编辑
根据 docs,您可以直接调用 $q.resolve()
而无需创建中间延迟对象 - 即 $q.defer().resolve()
一个小的重构,下面的代码可以避免你在不需要的时候创建一个延迟。如果文件已经加载,您只需要创建一个新的 deferred。否则,您可以 return 调用 Users.getFiles()
,像这样:
function getUserFiles(user) {
// Files already have been loaded
if (userFiles[user.id]) {
// See Edit Note
// return $q.defer().resolve(userFiles[user.id]);
return $q.resolve(userFiles[user.id]);
}
// Get files for the first time
return Users.getFiles(user)
.then(function(files) {
//Cache them
return (userFiles[user.id] = files);
});
}
此函数获取外部提供的用户文件列表API。一旦检索到数据,它就会被保存,因此下次调用它时 returns 之前保存的相同数据。此代码在控制器级别。
var userFiles = {};
function getUserFiles(user) {
var dfd = $q.defer();
// Files already have been loaded
if (userFiles[user.id]) {
dfd.resolve(userFiles[user.id]);
} else {
// Get files for the first time
Users.getFiles(user).then(function(files) {
userFiles[user.id] = files;
dfd.resolve(userFiles[user.id]);
});
}
return dfd.promise;
}
您将如何重构此代码以使其仅调用一次 dfd.resolve?
var userFiles = {};
function getUserFiles(user) {
var dfd = $q.defer();
if (!userFiles[user.id]) {
// Get files for the first time
Users.getFiles(user).then(function(files) {
userFiles[user.id] = files;
});
dfd.resolve(userFiles[user.id]);
}
return dfd.promise;
}
编辑 #2
我有一个甚至 更好 的片段给你:
function getUserFiles(user) {
return userFiles[user.id] || (userFiles[user.id] = Users.getFiles(user));
}
这将 userFiles[user.id]
设置为 return 由 Users.getFiles(user)
编辑并 return 的承诺。如果 userFiles[user.id]
已经设置(即它是 truth-y)那么它只是 return 之前解决的承诺。
使用这个超短代码段的缺点是您没有进行任何故障检查 - 并且可能最终缓存失败的请求 - 再一次,您也没有在其他代码中进行任何故障检查。
编辑
根据 docs,您可以直接调用 $q.resolve()
而无需创建中间延迟对象 - 即 $q.defer().resolve()
一个小的重构,下面的代码可以避免你在不需要的时候创建一个延迟。如果文件已经加载,您只需要创建一个新的 deferred。否则,您可以 return 调用 Users.getFiles()
,像这样:
function getUserFiles(user) {
// Files already have been loaded
if (userFiles[user.id]) {
// See Edit Note
// return $q.defer().resolve(userFiles[user.id]);
return $q.resolve(userFiles[user.id]);
}
// Get files for the first time
return Users.getFiles(user)
.then(function(files) {
//Cache them
return (userFiles[user.id] = files);
});
}