I've been told that this function (or one very similar) is an example of deferred anti-pattern
function writeFile(file)
{
return new WinJS.Promise(function (complete, error, progress) {
if (file) {
Windows.Storage.FileIO.writeTextAsync(file, getEditorContent()).done(
function () {
currentFile = file;
WinJS.log && WinJS.log("writeFile: file written: " + file.name + "", "MyApp", "info");
complete();
},
function (error) {
WinJS.log && WinJS.log("writeFile: error writing File " + file.name + "", "MyApp", "error");
error();
}
);
}
else {
WinJS.log && WinJS.log("writeFile: error writing File: file object was null", "MyApp", "error");
error();
}
});
}
I need all three branches of this to return a promise, as this method is part of a promise chain. If I want to avoid the dreaded anti-pattern, I should supposedly do this:
function writeFile(file)
{
if (file) {
return Windows.Storage.FileIO.writeTextAsync(file, getEditorContent());
}
else {
WinJS.log && WinJS.log("writeFile: error writing File: file object was null", "MyApp", "error");
return WinJS.Promise.as();
}
}
And move my done()
code to the calling function. However, writeFile
is called from a number of locations in my app, and so in the interests of DRY performs some functions after writeTextAsync
. I don't want to move these to the calling function, so I'm left doing this.
function writeFile(file)
{
if (file) {
Windows.Storage.FileIO.writeTextAsync(file, getEditorContent()).done(
function () {
currentFile = file;
WinJS.log && WinJS.log("writeFile: file written: " + file.name + "", "MyApp", "info");
return WinJS.Promise.as();
},
function (error) {
WinJS.log && WinJS.log("writeFile: error writing File " + file.name + "", "MyApp", "error");
return WinJS.Promise.as();
}
);
}
else {
WinJS.log && WinJS.log("writeFile: error writing File: file object was null", "MyApp", "error");
return WinJS.Promise.as();
}
}
It seems like I've just swapped a wrapped promise for three returned ones. How or why is this better?
UPDATE
I think I just realised I can return a then
promise that writeTextAsync
returns:
function writeFile(file)
{
if (file) {
// I can return this, right?
return Windows.Storage.FileIO.writeTextAsync(file, getEditorContent()).then(
function () {
currentFile = file;
WinJS.log && WinJS.log("writeFile: file written: " + file.name + "", "MyApp", "info");
},
function (error) {
WinJS.log && WinJS.log("writeFile: error writing File " + file.name + "", "MyApp", "error");
return WinJS.Promise.wrapError(error)
}
);
}
else {
WinJS.log && WinJS.log("writeFile: error writing File: file object was null", "MyApp", "error");
return WinJS.Promise.wrapError("error writing File: file object was null")
}
}