【问题标题】:How do I use promises in a Chrome extension?如何在 Chrome 扩展程序中使用 Promise?
【发布时间】:2018-06-13 18:58:18
【问题描述】:

我要做的是创建一个 chrome 扩展,使用 promises 创建新的嵌套书签文件夹。

执行此操作的函数是 chrome.bookmarks.create()。但是我不能只是 循环这个函数,因为 chrome.bookmarks.create 是异步的。我需要等到创建文件夹并获取它的新 ID,然后再继续它的子文件夹。

承诺似乎是要走的路。不幸的是,我找不到使用带有自己的回调的异步调用的最小工作示例,例如 chrome.bookmarks.create。

我已经阅读了一些教程1234。我已经搜索了 stackOverflow,但所有问题似乎都不是关于 chrome 扩展库的普通承诺。

我不想使用插件或库:没有 node.js 或 jquery 或 Q 或其他。

我尝试按照教程中的示例进行操作,但很多事情没有意义。例如,教程指出:

promise 构造函数接受一个参数——一个带有两个参数的回调 参数:解析和拒绝。

但后来我看到这样的例子:

const wait = ms => new Promise(resolve => setTimeout(resolve, ms));

这对我来说是个谜。

另外,如果 resolve() 从未被定义,你怎么能调用它呢?教程中的示例似乎与现实生活中的代码不匹配。另一个例子是:

function isUserTooYoung(id) {
   return openDatabase() // returns a promise   
.then(function(col) {return find(col, {'id': id});})

如何传入col,或者得到任何结果!

因此,如果有人能给我一个带有自己回调的异步函数的承诺的最小工作示例,将不胜感激。

所以想要代码,所以这是我的非工作尝试:

//loop through all
function createBookmarks(nodes, parentid){  

  var jlen = nodes.length;
  var i;
  var node;
  for(var i = 0; i < nodes.length; i++){
        var node = nodes[i];

        createBookmark(node, parentid);
  }
}

//singular create
function createBookmark(node, parentid){  
      var bookmark = { 
    parentId : parentid,
    index : node['index'],
    title : node['title'],
    url : node['url']
  }

  var callback = function(result){
    console.log("creation callback happened.");
    return result.id;  //pass ID to the callback, too
  }

    var promise = new Promise(function(resolve, reject) {

        var newid = chrome.bookmarks.create(bookmark, callback)

      if (newid){
        console.log("Creating children with new id: " + newid);
        resolve( createBookmarks(bookmark.children, newid));
      }

    });
}

//allnodes already exists
createBookmarks(allnodes[0],"0");

只是不起作用。回调的结果始终是未定义的,它应该是,而且我看不到 Promise 对象如何改变任何东西。当我尝试使用 promise.then() 时,我同样感到困惑。

var newid = promise.then(  //wait for a response?
            function(result){
            return chrome.bookmarks.create(bookmark, callback); 
            }
        ).catch(function(error){
            console.log("error " + error);
        });  

        if (node.children) createBookmarks(node.children, newid);

同样,newid 始终是未定义的,因为 bookmarks.create() 当然是异步的。

感谢您提供的任何帮助。

【问题讨论】:

  • 接受回调的 Chrome API 方法没有任何返回值,如您在文档中所见。它们仅在回调中提供结果。顺便说一句,您可以简单地使用Mozilla's polyfill for Chrome

标签: google-chrome google-chrome-extension promise extension-methods


【解决方案1】:

老实说,您应该只使用web extension polyfill。手动承诺 chrome API 既浪费时间又容易出错。

如果您绝对坚持,这是您如何承诺 chrome.bookmarks.create 的示例。对于其他 chrome.* API,您还必须拒绝回调的错误参数。

function createBookmark(bookmark) {
  return new Promise(function(resolve, reject) {
    try {
      chrome.bookmarks.create(bookmark, function (result) {
        if (chrome.runtime.lastError) reject(chrome.runtime.lastError)
        else resolve(result)
      })
    } catch (error) {
      reject(error)
    }
  })
}


createBookmark({})
  .then(function (result) {
     console.log(result)
   }).catch(function (error) {
     console.log(error)
   })

要创建多个书签,您可以:

function createBookmarks(bookmarks) {
  return Promise.all(
    bookmarks.map(function (bookmark) {
      return createBookmark(bookmark)
    })
  )
}

createBookmarks([{}, {}, {}, {}])
  .catch(function (error) {
    console.log(error)
  })

【讨论】:

    【解决方案2】:

    利用回调函数总是最后一个参数的约定,我使用一个简单的辅助函数来promisify chrome API:

    function toPromise(api) {
      return (...args) => {
        return new Promise((resolve) => {
          api(...args, resolve);
        });
      };
    }
    

    并像这样使用它:

    toPromise(chrome.bookmarks.create)(bookmark).then(...);
    

    在我的用例中,它大部分时间都可以工作。

    【讨论】:

      猜你喜欢
      • 2013-02-04
      • 1970-01-01
      • 2016-07-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多