Revert Promises in file API to callbacks.
Promises do not seem reliable as they are in Chrome 34. Rather than continue to implement hacks that can work around these problems, let's just go back to callbacks. Maybe we don't need to be on the cutting edge _all_ the time.
This commit is contained in:
parent
a30bb4687e
commit
12870d3b1d
7 changed files with 89 additions and 121 deletions
|
@ -21,7 +21,7 @@ define([
|
|||
if (window.launchData) {
|
||||
window.launchData.forEach(function(file) {
|
||||
var f = new File(file.entry);
|
||||
f.read().then(function(contents) {
|
||||
f.read(function(err, contents) {
|
||||
sessions.addFile(contents, f);
|
||||
}, dialog);
|
||||
});
|
||||
|
@ -37,7 +37,7 @@ define([
|
|||
//files get opened in a tab
|
||||
if (entry.isFile) {
|
||||
var f = new File(entry);
|
||||
return f.read().then(function(data) {
|
||||
return f.read(function(err, data) {
|
||||
sessions.addFile(data, f);
|
||||
}, dialog);
|
||||
//directories get added to project
|
||||
|
@ -74,7 +74,7 @@ define([
|
|||
}
|
||||
files.map(function(entry) {
|
||||
var f = new File(entry);
|
||||
return f.read().then(function(data) {
|
||||
return f.read(function(err, data) {
|
||||
sessions.addFile(data, f);
|
||||
}, dialog);
|
||||
});
|
||||
|
@ -103,12 +103,12 @@ define([
|
|||
command.on("session:revert-file", function(c) {
|
||||
var tab = sessions.getCurrent();
|
||||
if (!tab.file) return;
|
||||
tab.file.read().then(function(data) {
|
||||
tab.file.read(function(err, data) {
|
||||
tab.setValue(data);
|
||||
tab.modified = false;
|
||||
tab.modifiedAt = new Date();
|
||||
sessions.renderTabs();
|
||||
c();
|
||||
if (c) c();
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -166,8 +166,10 @@ define([
|
|||
|
||||
command.on("session:insert-from-file", function(c) {
|
||||
var f = new File();
|
||||
f.open().then(f.read.bind(f)).then(function(text) {
|
||||
editor.execCommand("insertstring", text);
|
||||
f.open(function() {
|
||||
f.read(function(err, text) {
|
||||
editor.execCommand("insertstring", text);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -185,20 +187,18 @@ define([
|
|||
data.retained,
|
||||
function(id, i, c) {
|
||||
var file = new File();
|
||||
file
|
||||
.restore(id)
|
||||
.then(function() {
|
||||
return file.read();
|
||||
})
|
||||
.then(function(data) {
|
||||
file.restore(id, function() {
|
||||
file.read(function(err, data) {
|
||||
if (err) {
|
||||
failures.push(id);
|
||||
return c(null);
|
||||
}
|
||||
c({
|
||||
value: data,
|
||||
file: file
|
||||
});
|
||||
}, function(err) {
|
||||
failures.push(id);
|
||||
c(null);
|
||||
});
|
||||
});
|
||||
},
|
||||
function(restored) {
|
||||
restored = restored.filter(function(d) { return d });
|
||||
|
@ -222,19 +222,16 @@ define([
|
|||
|
||||
var reset = function() {
|
||||
var tabs = sessions.getAllTabs();
|
||||
var virtuals = [];
|
||||
tabs.forEach(function(tab) {
|
||||
if (tab.file && tab.file.virtual) {
|
||||
var v = tab.file.read().then(function(data) {
|
||||
virtuals++;
|
||||
tab.file.read(function(err, data) {
|
||||
tab.setValue(data);
|
||||
tab.modified = false;
|
||||
session.renderTabs();
|
||||
});
|
||||
virtuals.push(v);
|
||||
}
|
||||
});
|
||||
Promise.all(virtuals).then(function() {
|
||||
setTimeout(sessions.renderTabs, 10);
|
||||
});
|
||||
};
|
||||
|
||||
command.on("init:startup", init);
|
||||
|
|
14
js/main.js
14
js/main.js
|
@ -16,20 +16,6 @@ require([
|
|||
"storage/syncfile"
|
||||
], function(command, Settings, dialog, sessions, M) {
|
||||
|
||||
//Promises appear to be buggy during startup, but resolving one will fix it
|
||||
//Rinse and repeat until init:complete fires
|
||||
//TODO: remove once we can, this is stupid
|
||||
var promiseBug = false;
|
||||
command.on("init:complete", function() {
|
||||
promiseBug = true;
|
||||
});
|
||||
var cycle = function() {
|
||||
new Promise(function(p) { p() });
|
||||
console.log("waiting");
|
||||
if (!promiseBug) setTimeout(cycle);
|
||||
};
|
||||
cycle();
|
||||
|
||||
var frame = chrome.app.window.current();
|
||||
|
||||
var setTheme = function() {
|
||||
|
|
|
@ -16,7 +16,7 @@ define([
|
|||
};
|
||||
|
||||
File.prototype = {
|
||||
open: function(mode) {
|
||||
open: function(mode, c) {
|
||||
var self = this;
|
||||
mode = mode || "open";
|
||||
//mode is "open" or "save"
|
||||
|
@ -24,45 +24,40 @@ define([
|
|||
"open": "openWritableFile",
|
||||
"save": "saveFile"
|
||||
};
|
||||
var deferred = M.deferred();
|
||||
|
||||
chrome.fileSystem.chooseEntry({
|
||||
type: modes[mode]
|
||||
}, function(entry) {
|
||||
//cancelling acts like an error, but isn't.
|
||||
if (!entry) return deferred.fail(chrome.runtime.lastError);
|
||||
if (!entry) return c(chrome.runtime.lastError);
|
||||
self.entry = entry;
|
||||
deferred.done(self)
|
||||
c(null, self);
|
||||
});
|
||||
|
||||
return deferred.promise();
|
||||
},
|
||||
|
||||
read: function() {
|
||||
read: function(c) {
|
||||
var self = this;
|
||||
var deferred = M.deferred();
|
||||
|
||||
if (!self.entry) {
|
||||
console.error(self);
|
||||
deferred.fail("File not opened");
|
||||
c("File not opened");
|
||||
}
|
||||
var reader = new FileReader();
|
||||
reader.onload = function() {
|
||||
deferred.done(reader.result);
|
||||
c(null, reader.result);
|
||||
};
|
||||
reader.onerror = function(err) {
|
||||
console.error("File read error!");
|
||||
deferred.fail(err);
|
||||
c(err);
|
||||
};
|
||||
self.entry.file(function(f) {
|
||||
reader.readAsText(f);
|
||||
});
|
||||
|
||||
return deferred.promise();
|
||||
},
|
||||
|
||||
write: function(data) {
|
||||
write: function(data, c) {
|
||||
var self = this;
|
||||
c = c || function() {};
|
||||
if (!self.entry) {
|
||||
//guard against cases where we accidentally write before opening
|
||||
return self.open("save").then(function() {
|
||||
|
@ -70,8 +65,6 @@ define([
|
|||
});
|
||||
}
|
||||
|
||||
var deferred = M.deferred();
|
||||
|
||||
M.chain(
|
||||
//check permissions
|
||||
function(next) {
|
||||
|
@ -85,7 +78,7 @@ define([
|
|||
self.entry = entry;
|
||||
next();
|
||||
} else {
|
||||
deferred.fail("Couldn't open file as writable");
|
||||
c("Couldn't open file as writable");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -96,12 +89,12 @@ define([
|
|||
self.entry.createWriter(function(writer) {
|
||||
writer.onerror = function(err) {
|
||||
console.error(err);
|
||||
deferred.fail(err);
|
||||
c(err);
|
||||
}
|
||||
writer.onwriteend = function() {
|
||||
//after truncation, actually write the file
|
||||
writer.onwriteend = function() {
|
||||
deferred.done();
|
||||
c();
|
||||
self.onWrite();
|
||||
}
|
||||
var blob = new Blob([data]);
|
||||
|
@ -111,53 +104,44 @@ define([
|
|||
});
|
||||
}
|
||||
);
|
||||
|
||||
return deferred.promise();
|
||||
},
|
||||
|
||||
stat: function() {
|
||||
stat: function(c) {
|
||||
var self = this;
|
||||
var promise = new Promise(function(ok, fail) {
|
||||
if (self.entry) {
|
||||
return self.entry.file(function(f) {
|
||||
ok(f);
|
||||
});
|
||||
}
|
||||
fail("No file entry");
|
||||
});
|
||||
return promise;
|
||||
if (self.entry) {
|
||||
return self.entry.file(function(f) {
|
||||
c(null, f);
|
||||
});
|
||||
}
|
||||
c("No file entry");
|
||||
},
|
||||
|
||||
retain: function() {
|
||||
return chrome.fileSystem.retainEntry(this.entry);
|
||||
},
|
||||
|
||||
restore: function(id) {
|
||||
restore: function(id, c) {
|
||||
var self = this;
|
||||
var deferred = M.deferred();
|
||||
|
||||
chrome.fileSystem.isRestorable(id, function(is) {
|
||||
if (is) {
|
||||
chrome.fileSystem.restoreEntry(id, function(entry) {
|
||||
if (!entry) return deferred.fail("restoreEntry() failed for " + id);
|
||||
if (!entry) return c("restoreEntry() failed for " + id);
|
||||
self.entry = entry;
|
||||
deferred.done();
|
||||
c();
|
||||
});
|
||||
} else {
|
||||
deferred.fail("isRestorable() returned false for " + id);
|
||||
c("isRestorable() returned false for " + id);
|
||||
}
|
||||
});
|
||||
|
||||
return deferred.promise();
|
||||
},
|
||||
|
||||
getPath: function() {
|
||||
getPath: function(c) {
|
||||
var self = this;
|
||||
var promise = new Promise(function(ok, fail) {
|
||||
if (!self.entry) return fail("No backing entry, cannot get path")
|
||||
chrome.fileSystem.getDisplayPath(self.entry, ok);
|
||||
if (!self.entry) return fail("No backing entry, cannot get path");
|
||||
chrome.fileSystem.getDisplayPath(self.entry, function(path) {
|
||||
c(null, path);
|
||||
});
|
||||
return promise;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -30,27 +30,25 @@ define([
|
|||
};
|
||||
SyncFile.prototype = {
|
||||
name: "",
|
||||
open: function(name) {
|
||||
open: function(name, c) {
|
||||
this.name = name;
|
||||
this.entry.name = name;
|
||||
var self = this;
|
||||
var promise = new Promise(function(ok, fail) {
|
||||
resolve(self);
|
||||
});
|
||||
return promise;
|
||||
if (c) c(null, this);
|
||||
},
|
||||
read: function() {
|
||||
read: function(c) {
|
||||
var name = this.name;
|
||||
return sync.get(this.name);
|
||||
sync.get(this.name).then(function(data) {
|
||||
c(null, data);
|
||||
});
|
||||
},
|
||||
write: function(content) {
|
||||
var self = this;
|
||||
write: function(content, c) {
|
||||
return sync.set(this.name, content).then(function() {
|
||||
command.fire("settings:change-local");
|
||||
c();
|
||||
});
|
||||
},
|
||||
retain: function() { return false; },
|
||||
restore: function() { return new Promise.reject() }
|
||||
restore: function(c) { c("Cannot restore sync storage files") }
|
||||
};
|
||||
|
||||
return SyncFile;
|
||||
|
|
31
js/tab.js
31
js/tab.js
|
@ -52,10 +52,10 @@ define([
|
|||
this.fileName = file.entry.name;
|
||||
this.modifiedAt = new Date();
|
||||
var self = this;
|
||||
if (!this.file.virtual) file.getPath().then(function(path) {
|
||||
if (!this.file.virtual) file.getPath(function(err, path) {
|
||||
self.path = path;
|
||||
command.fire("session:render");
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
Tab.prototype.save = function(as) {
|
||||
|
@ -70,27 +70,30 @@ define([
|
|||
var deferred = M.deferred();
|
||||
|
||||
var whenOpen = function() {
|
||||
self.file.write(content).then(function() {
|
||||
self.file.write(content, function(err) {
|
||||
if (err) {
|
||||
return deferred.fail(err);
|
||||
}
|
||||
self.modifiedAt = new Date();
|
||||
self.modified = false;
|
||||
command.fire("session:render");
|
||||
deferred.done();
|
||||
}, deferred.fail.bind(deferred));
|
||||
});
|
||||
};
|
||||
|
||||
if (!self.file || as) {
|
||||
var file = new File();
|
||||
file.open("save")
|
||||
.then(function() {
|
||||
self.file = file;
|
||||
self.fileName = file.entry.name;
|
||||
delete self.syntaxMode;
|
||||
self.detectSyntax();
|
||||
}, function(err) {
|
||||
file.open("save", function(err) {
|
||||
if (err) {
|
||||
dialog(err);
|
||||
deferred.fail();
|
||||
})
|
||||
.then(whenOpen);
|
||||
return deferred.fail(err);
|
||||
}
|
||||
self.file = file;
|
||||
self.fileName = file.entry.name;
|
||||
delete self.syntaxMode;
|
||||
self.detectSyntax();
|
||||
whenOpen();
|
||||
});
|
||||
} else {
|
||||
whenOpen();
|
||||
}
|
||||
|
|
|
@ -138,15 +138,16 @@ define([
|
|||
self.render();
|
||||
var file = new File();
|
||||
file.onWrite = self.watchProjectFile.bind(self);
|
||||
file.restore(data.retainedProject).then(function(f) {
|
||||
file.read().then(function(data) {
|
||||
file.restore(data.retainedProject, function(err, f) {
|
||||
file.read(function(err, data) {
|
||||
if (err) {
|
||||
self.loading = false;
|
||||
self.render();
|
||||
return chrome.storage.local.remove("retainedProject");
|
||||
}
|
||||
self.projectFile = file;
|
||||
self.loadProject(JSON.parse(data));
|
||||
});
|
||||
}, function(err) {
|
||||
self.loading = false;
|
||||
self.render();
|
||||
return chrome.storage.local.remove("retainedProject");
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -336,7 +337,7 @@ define([
|
|||
if (!tab.file || tab.file.virtual) {
|
||||
return c(false);
|
||||
}
|
||||
tab.file.getPath().then(function(p) {
|
||||
tab.file.getPath(function(err, p) {
|
||||
if (p == path) {
|
||||
sessions.setCurrent(tab);
|
||||
found = true;
|
||||
|
@ -349,7 +350,7 @@ define([
|
|||
function() {
|
||||
if (found) return;
|
||||
var file = new File(node.entry);
|
||||
file.read().then(function(data) {
|
||||
file.read(function(err, data) {
|
||||
sessions.addFile(data, file);
|
||||
});
|
||||
}
|
||||
|
@ -375,7 +376,7 @@ define([
|
|||
var file = new File();
|
||||
var watch = this.watchProjectFile.bind(this);
|
||||
var self = this;
|
||||
file.open("save").then(function() {
|
||||
file.open("save", function() {
|
||||
file.write(json);
|
||||
var id = file.retain();
|
||||
chrome.storage.local.set({retainedProject: id});
|
||||
|
@ -389,21 +390,20 @@ define([
|
|||
openProjectFile: function() {
|
||||
var file = new File();
|
||||
var self = this;
|
||||
file
|
||||
.open()
|
||||
.then(file.read.bind(file))
|
||||
.then(function(data) {
|
||||
file.open(function() {
|
||||
file.read(function(err, data) {
|
||||
self.loadProject(data);
|
||||
var id = file.retain();
|
||||
chrome.storage.local.set({retainedProject: id});
|
||||
self.projectFile = file;
|
||||
file.onWrite = self.watchProjectFile.bind(self);
|
||||
});
|
||||
file.onWrite = self.watchProjectFile;
|
||||
});
|
||||
},
|
||||
|
||||
watchProjectFile: function() {
|
||||
var self = this;
|
||||
this.projectFile.read().then(function(data) {
|
||||
this.projectFile.read(function(err, data) {
|
||||
self.loadProject(data);
|
||||
});
|
||||
},
|
||||
|
@ -445,7 +445,7 @@ define([
|
|||
return dialog("No project opened.");
|
||||
}
|
||||
var self = this;
|
||||
this.projectFile.read().then(function(data) {
|
||||
this.projectFile.read(function(err, data) {
|
||||
sessions.addFile(data, self.projectFile);
|
||||
});
|
||||
},
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "Caret",
|
||||
"description": "Professional text editing for Chrome and Chrome OS",
|
||||
"version": "1.4.6",
|
||||
"version": "1.4.7",
|
||||
"manifest_version": 2,
|
||||
"icons": {
|
||||
"128": "icon-128.png"
|
||||
|
|
Loading…
Reference in a new issue