I am developing a chrome extension that makes use of 'chrome.storage.local' and am trying to create a promise out of the chrome.storage.local.get() async function, which I would like to be able to throw exceptions from as well as reject/resolve. I've tried testing this with the below implementation, but am seeing an error which from the console logs seems to be from the " readLocalStorageObj("prefs").then(function(item) {
" line (the error is shown below after the code).
require([
"libs/bluebird"
],
function(Promise) {
function readLocalStorageObj(itemName) {
var localReadResult = Promise.method(function(item) {
console.log("localReadResult():", item);
// if (chrome.runtime.lastError) {
// throw new Error(chrome.runtime.lastError);
// }
if (Object.getOwnPropertyNames(item).length > 0) {
console.log('in if part');
return item;
}
else {
console.log('in else part');
// throw new Error("my test exception");
return undefined;
}
});
chrome.storage.local.get(itemName, localReadResult);
return localReadResult;
};
readLocalStorageObj("prefs").then(function(item) {
console.log('success', item);
}, function(e) {
console.log('fail', e);
}).error(function(e) {
console.log('error', e);
}).catch(ChromeRuntimeError, function(e) {
console.log('catch', e);
}).finally(function(a) {
console.log('finally', a);
});
});
Error:
Uncaught TypeError: Object function Promise$_method() { var value; switch(arguments.length) { case 0: value = tryCatch1(fn, this, void 0); break; case 1: value = tryCatch1(fn, this, arguments[0]); break; case......n'
I can't quite seem to figure out what the cause for this is ,and would really appreciate any help with this.
TIA
Try creating the promise like this:
require([
"libs/bluebird"
],
function(Promise) {
function readLocalStorageObj(itemName) {
return new Promise(function(resolve, reject) {
chrome.storage.local.get(itemName, function(item) {
if (chrome.runtime.lastError) {
return reject(chrome.runtime.lastError);
}
if (Object.getOwnPropertyNames(item).length > 0) {
return resolve(item);
}
reject(new Error("empty item"));
});
});
}
readLocalStorageObj("prefs").then(function(item) {
console.log('success', item);
}, function(e) {
console.log('fail', e);
}).error(function(e) {
console.log('error', e);
}).catch(ChromeRuntimeError, function(e) {
console.log('catch', e);
}).finally(function(a) {
console.log('finally', a);
});
});
However if you need to use promises with extension callback conventions a lot this will result in a lot of boilerplate.
To avoid boilerplate, you can define a generic promisification function for this convention:
function promisfyChrome(fn, ctx) {
return function() {
var args = [].slice.call(arguments);
var self = ctx || this;
return new Promise(function(resolve, reject) {
args.push(function(value) {
if (chrome.runtime.lastError)
return reject(chrome.runtime.lastError);
resolve(value);
});
fn.apply(self, args);
})
};
}
Usage:
require([
"libs/bluebird"
],
function(Promise) {
var chromeLocalStorageGet = promisifyChrome(chrome.storage.local.get, chrome.storage.local);
function readLocalStorageObj(itemName) {
return chromeLocalStorageGet(itemName).then(function(item) {
if (Object.getOwnPropertyNames(item).length > 0) {
return item;
}
throw new Error("empty item");
});
}
readLocalStorageObj("prefs").then(function(item) {
console.log('success', item);
}, function(e) {
console.log('fail', e);
}).error(function(e) {
console.log('error', e);
}).catch(ChromeRuntimeError, function(e) {
console.log('catch', e);
}).finally(function(a) {
console.log('finally', a);
});
});
Btw:
readLocalStorageObj("prefs").then(function(item) {
console.log('success', item);
}, function(e) {
console.log('fail', e);
}).error(function(e) {
console.log('error', e);
}).catch(ChromeRuntimeError, function(e) {
console.log('catch', e);
}).finally(function(a) {
console.log('finally', a);
});
Is in this case equivalent to:
readLocalStorageObj("prefs").then(function(item) {
console.log('success', item);
}).catch(Error, function(e) {
console.log('fail', e);
}).error(function(e) {
console.log('error', e);
}).catch(ChromeRuntimeError, function(e) {
console.log('catch', e);
}).finally(function(a) {
console.log('finally', a);
});
As you can see the first catch
already catches any kind of error so the other catches are never triggered. You will want to do it in the opposite way - more specific catch handlers first and more general ones last.
Also, using .then
with 2 functions is really hard to read so it's not recommended. Prefer .then(fn).catch(fn2)
over .then(fn, fn2)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.