【问题标题】:JavaScript bookmarklet code to get URL of tab that was launched from current tab用于获取从当前选项卡启动的选项卡 URL 的 JavaScript 小书签代码
【发布时间】:2017-08-26 08:22:18
【问题描述】:

我正在尝试开发一个书签。小书签的目的是显示当前选项卡和新选项卡的 URL,该选项卡是通过 window.open 调用而启动的。为简化起见,假设launcher.com 启动一个随机URL 进行访问。

function getBothURLs() { 
    var currentURL, newWin;

    function launchNew () {
        currentURL = window.location.href; 
        newWin     = window.open("https://www.launcher.com");
    }

    launchNew();
    alert(currentURL); 
    alert(newWin.location.href); // displays 'about:blank'
}

我无法获取新启动标签的 URL。 alert()(在下面函数的最后)没有正确显示新启动选项卡的 URL;而是显示

 about:blank

当我在 Chrome 控制台中对此进行故障排除时,我将 var currentURL, newWin 的定义移到了 getTwoURLs() 函数的范围之外。当我从控制台中调用函数getBothURLs() 时,currentURLnewWin 都有有效数据。

应该如何修改函数getBothURLs()才能达到预期的目的?

【问题讨论】:

  • 最好将随机 url 值添加到变量中,例如:newUrl = "google.com",然后将值分配给 newWin 变量,例如:newWin = window.open(newUrl);完成此操作后,尝试输入以下行:alert(newUrl);我希望它会起作用。
  • 我假设您正在打开不同来源的网址。您可以访问其他 url 的代码库吗? @AntonySUTHAKARJ 的评论很有道理,你能解释一下为什么这对你不起作用吗?
  • 出于所有实际目的,URL 是在同一来源上打开的。但由于 URL 将包含一个自动生成的十六进制数字作为其中的一部分,因此无法提前知道。
  • 是否有理由不将urlToOpen 作为参数传递给getBothURLs?我想这里应该有一个带有输入和输出的函数。

标签: javascript url tabs bookmarklet


【解决方案1】:

来自 MDN 的关于 window.open 的注释:

...远程网址不会立即加载。当 window.open() 返回时,窗口总是包含 about:blank。 URL 的实际提取是延迟,并在当前脚本块执行完毕后开始...

在上述情况下,current 块以 getBothURLs() 函数结尾,但您尝试检查该块本身内的新 URL,根据上面的引用,您会看到 @987654323 @网址。
要解决此问题,只需将查找推迟到下一个任务。您可以使用setTimeout 之类的东西将查找发布到下一个任务,或者如果您希望从函数返回值,则使用 Promises 更好。

示例实现可能如下所示:

function getBothURLs() {
  return new Promise((resolve) => {
    var newWin = window.open("//www.stackoverflow.com");
    setTimeout(() => resolve(newWin))
  }).then((win) => {
    return new Promise((resolve, reject) => {
       var check = setInterval(() => {
         try { 
           if(win.location.href !== "about:blank"){
               clearInterval(check);
               resolve(win.location.href)
           }
         } catch(e) {
           clearInterval(check);
           reject(e);
         }
       }, 50)
     })
   })
}

getBothURLs().then(url => console.log(url))

虽然上述解决方案有效,但我仍然建议您将新窗口的 URL 存储在一个变量中,然后使用该变量调用 open

更新 1:

此示例 sn-p 使用可以返回两个 url 的非承诺回调版本。虽然,也可以修改 promise 版本以返回两个 url,但是由于 OP 在 cmets 中要求提供非基于 promise 的版本,所以我提供了新的 sn-p。 看看:

function getBothURLs(callback){
  var current = window.location.href;
  var win = window.open("https://stackoverflow.com");
  var check =  setInterval(() => {
    try {
      if(win.location.href !== "about:blank"){
        clearInterval(check);
        callback(null, current, win.location.href)
      }
    } catch(e) {
      clearInterval(check);
      callback(e);
    }
  }, 50);
}

getBothURLs((err, _cur, _new) => {
  if(err){
    // some error occurred, probably a cross-origin access
    console.error("Failed to get URL", err);
    return;
  }

  console.log(`Current: ${_cur} New: ${_new}`);
})

【讨论】:

  • 当有跨域链接时,这段代码进入一个连续循环。其次,它不会返回两个 URL(它只返回新的 URL)。而且,很高兴知道 Promise 可以做什么,但这不是矫枉过正吗?
  • @lifebalance 好收获!我已经修复了 sn-p 以处理错误检查并防止无限循环,但我想指出之前对 OP 的评论,你提到过 - “..出于所有实际目的,正在打开 URL同源” - 所以我没有在早期版本中包含它,但 nvm,一点错误检查总是好的
  • @lifebalance 就 Promise 而言,我认为我的解决方案使用 async 方法来检查 url(setInterval 和所有),所以你需要一些方法来完成后通知来电者,所以我在这里使用了 Promise...如果您愿意,您也可以选择 Callbacks...
  • 感谢您的修复。如何使函数返回两个 URL?
  • 如果不是太麻烦,也可以了解一下非Promise回调版本。
猜你喜欢
  • 1970-01-01
  • 2023-03-22
  • 2013-04-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-21
  • 2014-09-12
相关资源
最近更新 更多