使用 Bluebird 承诺 chrome API

Promisify chrome API using Bluebird

我正在尝试使用 Bluebird.js 来承诺 chrome.storage.sync.get。我看到 bluebird http://bluebirdjs.com/docs/working-with-callbacks.html 站点上的所有示例都使用 Promise.promisify(require(someAPI))。我试着做 const storageGet = Promise.promisify(chrome.storage.sync.get);(如果这会影响任何东西,我没有要求),然后调用

async function() {
  return await storageGet('config', function (result) {
    // do stuff
  })
};

控制台错误是

Unhandled rejection Error: Invocation of form get(string, function, function) 
doesn't match definition get(optional string or array or object keys, function 
callback)

我的理解(当然对 Promises 和 bluebird 了解不多)是 storageGet 被传递了错误的参数?但是 chrome.storage.sync.get 需要传递一个字符串和一个回调函数,所以我不太确定出了什么问题。此外,我可能完全不了解我如何承诺 chrome 存储。

我知道有一个 chrome 在 http://bluebirdjs.com/docs/api/promise.promisifyall.html#option-promisifier 承诺的示例,但老实说,我对承诺不太熟悉,无法理解该示例中发生的事情。

我应该通过某种方式来承诺 chrome 存储而不是我正在做的方式吗?

您想使用 Bluebird 承诺的函数的回调 API 必须符合 NodeJS 回调约定:"error-first, single-parameter"(如前所述 HERE). According to the storage sync documentation 它的 API 不符合Bluebird要求的:

StorageArea.get(string or array of string or object keys, function callback)

/* Callback with storage items, or on failure (in which case runtime.lastError will be set).

The callback parameter should be a function that looks like this:

function(object items) {...};*/

根本没有错误参数。这种方法甚至没有抛出任何错误。它只公开结果。您可以通过使用 Promise:

包装给定的方法轻松地将它变成基于 Promise 的 API
function getFromStorageSync(key) {
  return new Promise(function(resolve) {
    chrome.storage.sync.get(key, function(items) {
      resolve(items)
    })
  })
}

getFromStorageSync('someKey').then(function(items) { console.log(items) })

更通用一些,在设置 chrome.runtime.lastError 时会捕获错误。

/**
 * Converts asynchronous chrome api based callbacks to promises
 *
 * @param {function} fn
 * @param {arguments} arguments to function
 * @returns {Promise} Pending promise returned by function
 */
var promisify = function (fn) {
  var args = Array.prototype.slice.call(arguments).slice(1);
  return new Promise(function(resolve, reject) {
    fn.apply(null, args.concat(function (res) {
      if (chrome.runtime.lastError) {
        return reject(chrome.runtime.lastError);
      }
      return resolve(res);
    }));
  });
};