本文章是由機器翻譯。

Windows 8.1 上的 WinJS

使用 JavaScript 建置更有效率的 Windows 市集應用程式:錯誤處理

Eric Schmidt

信不信由您,有時應用程式開發人員編寫代碼,不工作。或代碼工作但是非常低效和佔用的記憶體。然而,更糟糕的是低效的代碼結果在可憐的 UX,發瘋的使用者和令人信服的他們要卸載該應用程式並留下不好的評價。

我要探索構建與 JavaScript Windows 存儲應用程式時可能遇到的常見的性能和效率問題。在這篇文章,我看看,JavaScript (WinJS) 使用 Windows 庫錯誤處理的最佳做法。在今後的文章中,我將討論技術做的工作,而不會阻塞 UI 執行緒,具體地使用 Web 工人或新的 WinJS.Utilities.Scheduler API 在 WinJS 2.0 中,作為 Windows 8.1 中都可以找到。我也將展現新的可預測物件生命週期模型在 WinJS 2.0 中,特別側重於何時及如何處置的控制項。

為每個主題領域,我集中在三件事情:

  • 錯誤或效率低下,可能會出現在 Windows 存儲應用程式中使用 JavaScript 生成的。
  • 找到這些錯誤和效率低下的診斷工具。
  • WinJS Api、 功能和最佳做法,可以改善的具體問題。

我提供一些有目的地錯誤的代碼,但是,請放心,我表示在代碼中什麼是或不是應該工作。

這些示威活動使用Visual Studio2013年、 Windows 8.1 和 WinJS 2.0 版。Visual Studio2013年中提供了許多我使用的診斷工具。如果您還沒有下載最新版本的工具,你可以讓他們從 Windows 開發中心 (bit.ly/K8nkk1)。新的診斷工具通過Visual Studio更新釋放的所以一定要定期檢查更新。

我假設構建 Windows 應用商店應用程式使用 JavaScript 的重大熟悉。如果你是相對較新的平臺,我建議開頭的基本的"Hello World"示例 (bit.ly/vVbVHC) 或更多的挑戰的 JavaScript 的希洛採樣 (bit.ly/SgI0AA)。

設置示例

第一,在Visual Studio2013年使用的導航應用程式範本,提供了一個良好的出發點點為一個基本的多頁應用程式中創建一個新的專案。我還將添加巡覽列上的控制項 (bit.ly/14vfvih) 到 default.html 頁位於根的解決方案,取代 AppBar 的代碼提供的範本。因為我想要表現出多個概念、 診斷工具和程式設計技術,我將向每個演示的應用程式添加新的一頁。這使得它更容易為我所有測試案例之間進行導航。

巡覽列上的完整 HTML 標籤所示圖 1。複製並將此代碼粘貼到您的解決方案,如果你在跟蹤這個示例。

圖 1 NavBar 控制項

<!-- The global navigation bar for the app.
-->
<div id="navBar" data-win-control="WinJS.UI.NavBar">
  <div id="navContainer" 
       data-win-control="WinJS.UI.NavBarContainer">
    <div id="homeNav" 
      data-win-control="WinJS.UI.NavBarCommand"
      data-win-options="{
        location: '/pages/home/home.html',
        icon: 'home',
        label: 'Home page'
    }">
    </div>
    <div id="handlingErrors"
      data-win-control="WinJS.UI.NavBarCommand"
      data-win-options="{
        location: '/pages/handlingErrors/handlingErrors.html',
        icon: 'help',
        label: 'Handling errors'
    }">
    </div>
    <div id="chainedAsync"
      data-win-control="WinJS.UI.NavBarCommand"
      data-win-options="{
        location: '/pages/chainedAsync/chainedAsync.html',
        icon: 'link',
        label: 'Chained asynchronous calls'
    }">
    </div>
  </div>
</div>

關於建設一個巡覽列的詳細資訊,簽出的某些現代應用程式列由Rachel Appel,例如在一個 msdn.microsoft.com/magazine/dn342878

您可以運行這個專案只是巡覽列,除了,按一下任何的導覽按鈕會引發一個異常在 navigator.js 中。後來在本文中,我將討論如何處理 navigator.js 中出現的錯誤。現在,請記住在回家的路上總是啟動 app­頁面,你需要用滑鼠右鍵按一下該應用程式,彈出巡覽列。

處理錯誤

很明顯,避免錯誤的最佳方法是釋放不引發錯誤的應用程式。在完美的世界,每個開發人員將編寫完美的代碼,從來沒有崩潰,從不引發異常。那完美的世界並不存在。

盡可能多的使用者更喜歡是完全無錯誤的應用程式,他們是非常擅長尋找新的和創造性的辦法,打破應用程式 — 你做夢都想不到的方式。因此,您需要將納入可靠的錯誤處理到您的應用程式。

用 JavaScript 和 HTML 生成的 Windows 存儲應用程式中的錯誤行為就像在正常的 Web 頁中的錯誤。當一個錯誤發生在一個允許的錯誤處理 (例如,該 < 腳本 > < 樣式 > 的文件物件模型 (DOM) 物件 或者 < img > 元素),為該元素的 onerror 事件引發。對於 JavaScript 呼叫堆疊中的錯誤,錯誤的調用直到抓到鏈上游記 (在 try/catch 塊,例如) 或直到它到達的視窗物件,引發 window.onerror 事件。

WinJS 提供了幾個圖層的什麼已經由 Microsoft Web 平臺提供給正常網頁您代碼的錯誤處理機會。在基本的層面上,不被困在一個 try/catch 塊中的任何錯誤或適用于 WinJS.Promise 的 onError 處理常式物件 (在當時或完成的方法,例如調用) 引發 WinJS.Application.onerror 事件。不久我會檢查的。

在實踐中,您可以偵聽其他各級除了 Application.onerror 錯誤。WinJS 和Visual Studio的工作室提供的範本,您還可以處理錯誤的頁面控制水準和導航一級。當雖然 app 是導航到並載入一個頁面,就會引發錯誤時,該錯誤會觸發的導航級別的錯誤處理頁級別的錯誤處理,然後最後應用程式級別的錯誤處理。您可以取消導航一級錯誤但仍將引發任何應用於該分頁錯誤處理常式的事件處理常式。

在本文中,我會看看每個圖層錯誤處理,開始與最重要的:Application.onerror 事件。

應用程式級別的錯誤處理

WinJS 提供的 WinJS.Application.onerror 事件 (bit.ly/1cOctjC),您的應用程式的最基本一道防線錯誤。它拿起由 window.onerror 捕獲所有錯誤"。 它還捉住承諾出該錯誤和管理的應用程式模型事件的過程中出現的任何錯誤。雖然在您的應用程式中,可以應用於 window.onerror 事件的事件處理常式,但你最好只使用 Application.onerror 為單個佇列的事件來監視。

一旦 Application.onerror 處理常式捕獲錯誤,您需要決定如何處理它。您可以有下列幾種選擇:

  • 阻塞的嚴重錯誤,警告使用者與一個消息對話方塊。一個關鍵的錯誤是一種影響 app 的繼續的運作,可能會要求使用者輸入來進行。
  • 資訊性和非阻塞的錯誤 (如未能同步或獲取線上資料),發出警報與彈出或內聯消息的使用者。
  • 對於不會影響使用者體驗的錯誤,默默地吞下了錯誤。
  • 在大多數情況下,將錯誤寫入 tracelog (特別是一種被掛接到分析引擎) 所以你可以獲取客戶遙測。可用分析的 Sdk,請訪問 Windows 服務目錄在 services.windowsstore.com ,然後點擊分析 (根據"按服務類型") 在左邊的清單中。

對於此示例,我會堅持的消息對話方塊。我打開了 default.js (/ js/default.js) 和添加所示的代碼圖 2 在主要的匿名函數,下面 app.oncheckpoint 事件的處理常式中。

圖 2 添加一個消息對話方塊

app.onerror = function (err) {
  var message = err.detail.errorMessage ||
    (err.detail.exception && err.detail.exception.message) ||
    "Indeterminate error";
  if (Windows.UI.Popups.MessageDialog) {
    var messageDialog =
      new Windows.UI.Popups.MessageDialog(
        message,
        "Something bad happened ...");
    messageDialog.showAsync();
    return true;
  }
}

在此示例中,錯誤事件處理常式顯示一條消息,告訴使用者發生了一個錯誤和錯誤。該事件處理常式返回真,以防止消息對話方塊中打開,直到使用者關閉它。(返回 true 還通知 WWAHost.exe 進程,已處理錯誤,它仍可以繼續)

現在,將創建一些為此代碼以處理錯誤。我會創建一個自訂的錯誤、 引發錯誤,然後抓住它的事件處理常式中。為此第一個示例中,添加一個新的資料夾名為處理­將錯誤記錄到頁資料夾。在資料夾中,添加一個新的頁面控制項通過按右鍵解決方案資源管理器中的專案並選擇添加 |新的專案。當我向我的專案中添加頁面控制項 handlingErrors 時,Visual Studio提供了 handlingErrors 資料夾 (/頁/handlingErrors) 中的三個檔:handlingErrors.html、 處理­Errors.js 和 handlingErrors.css。

我打開了 handlingErrors.html 並添加這個簡單的標記在 < 節 > 內 身體的標籤:

<!-- When clicked, this button raises a custom error.
-->
<button id="throwError">Throw an error!</button>

接下來,我打開 handlingErrors.js,向準備方法的 PageControl 物件,按鈕添加事件處理常式,如中所示圖 3。 我為上下文提供了整個 PageControl 定義在 handlingErrors.js 中。

圖 3 定義的 handlingErrors PageControl

// For an introduction to the Page Control template, see the following documentation:
// http://go.microsoft.com/fwlink/?LinkId=232511
(function () {
  "use strict";
  WinJS.UI.Pages.define("/pages/handlingErrors/handlingErrors.html", {
    ready: function (element, options) {
      // ERROR: This code raises a custom error.
throwError.addEventListener("click", function () {
        var newError = new WinJS.ErrorFromName("Custom error", 
          "I'm an error!");
        throw newError;
      });
    },
    unload: function () {
      // Respond to navigations away from this page.
},
    updateLayout: function (element) {
      // Respond to changes in layout.
}
  });
})();

現在我按 f5 鍵以運行該示例,導航到處理­的錯誤頁面,然後按一下"將引發錯誤!"按鈕。(如果你往下,你會看到一個對話方塊,通知您已引發錯誤的Visual Studio從。按一下繼續保持示例運行)。消息彈出一個對話方塊然後,出現錯誤,如中所示圖 4


圖 4 顯示在消息對話方塊中的自訂錯誤

自訂錯誤

Application.onerror 事件有一些有關它處理的錯誤的期望。創建自訂錯誤的最佳方法是使用 WinJS.ErrorFromName 物件 (bit.ly/1gDESJC)。創建的物件公開的錯誤處理常式進行語法分析的標準介面。

若要不使用 ErrorFromName 物件創建您自己的自訂錯誤,您需要實現一個 toString 方法返回的錯誤訊息。

否則,當您自訂錯誤引發時,Visual Studio調試器和消息對話方塊中顯示"[物件物件]。他們每個調用 toString 方法的物件,但因為沒有這種方法在直接物件中定義的它穿過的定義 toString 的原型繼承鏈。當它到達時不會有一個 toString 方法的物件基元類型,它調用該方法 (其中只顯示有關物件的資訊)。

頁級別錯誤處理

WinJS 中的 PageControl 物件提供錯誤處理應用程式的另一的層。WinJS 將調用 IPageControlMembers.error 方法時在頁的載入時發生錯誤。在載入頁面後,然而,IPageControlMembers.error 方法錯誤是由撿起來的 Application.onerror 事件處理常式,忽略頁面的錯誤方法。

我會將錯誤方法添加到 PageControl 表示 handleErrors 頁。錯誤方法 JavaScript 主控台中寫入Visual Studio中使用 WinJS.log。日誌記錄功能需要將開始第一次,所以我需要在我嘗試使用該方法之前調用 WinJS.Utilities.startLog。此外注意到我的 WinJS.log 成員存在前,請檢查其實叫。

HandleErrors.js 的完整代碼 (/ pages/handleErrors/handleErrors.js) 中所示圖 5

圖 5 完成 handleErrors.js

(function () {
  "use strict";
  WinJS.UI.Pages.define("/pages/handlingErrors/handlingErrors.html", {
    ready: function (element, options) {
      // ERROR: This code raises a custom error.      
      throwError.addEventListener("click", function () {
        var newError = {
          message: "I'm an error!",
          toString: function () {
            return this.message;
          }
        };
        throw newError;
      })
    },
    error: function (err) {
      WinJS.Utilities.startLog({ type: "pageError", tags: "Page" });
      WinJS.log && WinJS.log(err.message, "Page", "pageError");
    },
    unload: function () {
      // TODO: Respond to navigations away from this page.
},
    updateLayout: function (element) {
      // TODO: Respond to changes in layout.
}
  });
})();

WinJS.log

對 WinJS.Utilities.startLog 中所示的調用圖 5 啟動 WinJS.log helper 函數,預設情況下將輸出寫入到 JavaScript 主控台。而這將大大有助於在設計時為調試期間,它不允許您捕獲錯誤資料後使用者安裝了該應用程式。

準備好要發佈和部署的應用程式,您應該考慮創建您自己的實現的調用分析引擎的 WinJS.log。這使您可以收集關於您的應用程式的性能遙測資料,以便可以在您的應用程式的未來版本中解決不可預見的錯誤。只需確保客戶所知的資料收集和你清楚地列出哪些資料獲取收集的分析引擎在您的應用程式的私隱聲明。

請注意當您以這種方式覆蓋 WinJS.log,WinJS.log 函數將捕獲所有輸出,否則會去 JavaScript 主控台中,包括像調度程式的狀態更新的東西。這就是為什麼你需要通過有意義的名稱和對 WinJS.Utilities.startLog 的調用到鍵入的值,所以您可以篩選出你不想要的任何錯誤。

現在我會試著運行該示例並按一下"引發錯誤!"再。這會導致在完全相同的行為之前:Visual Studio拾取錯誤,然後 Application.onerror 事件觸發。JavaScript 主控台而不顯示在頁面載入後引發的錯誤,是因為與錯誤有關的任何消息。因此,該錯誤只由 Application.onerror 事件處理常式被撿起來。

那麼為什麼要使用 PageControl 錯誤處理?很好,它是用於捕獲並診斷錯誤在 HTML 中以聲明方式創建的 WinJS 控制項中特別有用。例如,我將添加以下的 HTML 標籤在 < 節 > 內 handleErrors.html 標記 (/ pages/handleErrors/handleErrors.html),下方的按鈕:

<!-- ERROR: AppBarCommands must be button elements by default
  unless specified otherwise by the 'type' property.
-->
<div data-win-control="WinJS.UI.AppBarCommand"></div>

現在我按 f5 鍵以運行該示例,然後定位到 handleErrors 頁。再次,直到被解雇,就會出現消息對話方塊。然而,在 JavaScript 主控台 (您需要切換回桌面要檢查此項) 中將顯示以下消息:

pageError: Page: Invalid argument: For a button, toggle, or flyout   command, the element must be null or a button element

請注意應用程式級別的錯誤處理看來即使我處理 PageControl (其中登錄錯誤) 中的錯誤。那麼如何可以無陷阱網頁上的有錯誤它向上冒泡到應用程式嗎?

陷阱一頁級別錯誤的最佳方法是添加錯誤處理的導航代碼。我會演示那下一步。

導航級別的錯誤處理

當我跑了前面的測試在 app.on­錯誤事件處理常式處理頁級別錯誤、 應用程式似乎停留在主頁上。然而,出於某些原因,後面的按鈕控制項出現。當我按一下後退按鈕時,它把我帶到 (已禁用) handlingErrors.html 頁。

這是因為在 navigator.js 中的導航代碼 (/ js/navigator.js),這導航應用程式專案範本中提供,仍然試圖要導航到的頁面,即使頁面已消退。此外,它返回到主頁導航並將出錯頁面添加到導航歷史記錄。這就是為什麼我後退按鈕之後,在看到主頁我已經試圖定位到 handlingErrors.html。

若要取消 navigator.js 中的錯誤,我替換 PageControl­Navigator._navigating 函數中的代碼與圖 6。您看到的導航功能包含對 WinJS.UI.Pages.render,返回一個承諾物件的調用。Render 方法嘗試從傳遞給它的 URI 中創建新的 PageControl 並將其插入到主機的一個因素。因為由此產生 PageControl 中包含錯誤,返回的承諾出現錯誤。要捕獲的導航過程中所引發的錯誤,我將一個錯誤處理常式添加到 onError 的方法參數的然後由該承諾物件公開。這有效地捕獲錯誤,防止它引發 Application.onerror 事件。

圖 6 PageControlNavigator._navigating 功能的 navigator.js

// Other PageControlNavigator code ...
// Responds to navigation by adding new pages to the DOM.
_navigating: function (args) {
  var newElement = this._createPageElement();
  this._element.appendChild(newElement);
  this._lastNavigationPromise.cancel();
  var that = this;
  this._lastNavigationPromise = WinJS.Promise.as().then(function () {
    return WinJS.UI.Pages.render(args.detail.location, newElement,
       args.detail.state);
  }).then(function parentElement(control) {
    var oldElement = that.pageElement;
    // Cleanup and remove previous element
    if (oldElement.winControl) {
      if (oldElement.winControl.unload) {
        oldElement.winControl.unload();
      }
      oldElement.winControl.dispose();
    }
    oldElement.parentNode.removeChild(oldElement);
    oldElement.innerText = "";
  },
  // Display any errors raised by a page control,
  // clear the backstack, and cancel the error.
function (err) {
    var messageDialog =
      new Windows.UI.Popups.MessageDialog(
        err.message,
        "Sorry, can't navigate to that page.");
    messageDialog.showAsync()
    nav.history.backStack.pop();
    return true;
  });
  args.detail.setPromise(this._lastNavigationPromise);
},
// Other PageControlNavigator code ...

在 WinJS 中的承諾

創建的承諾和束縛的承諾 — 和這樣做的最佳做法 — 已在許多其他地方,所以我就會跳過這篇文章中的討論。如果您需要更多的資訊,簽出的博客張貼內容由在克賴希 Brockschmidt bit.ly/1cgMAnu 或附錄 A 在他免費的電子書,"程式設計 Windows 存儲應用程式與 HTML、 CSS 和 JavaScript,第二版"(bit.ly/1dZwW1k)。

請注意修改 navigator.js 完全正確。雖然它由Visual Studio專案範本提供的它是您的應用程式的代碼的一部分,並可以但是您需要修改。

在 _navigating 函數中,我已經向最後 promise.then 調用添加錯誤處理常式。在錯誤處理常式顯示一個消息對話方塊 — 作為應用程式級錯誤處理 — 然後取消錯誤的返回 true。它還從導航歷史記錄中刪除頁面。

當我再次運行示例,定位到 handlingErrors.html 時,通知我的導航嘗試已失敗的消息對話方塊中見從應用程式級別的錯誤處理消息對話方塊中不會出現。

追蹤非同步鏈中的錯誤

在生成時在 JavaScript 中的應用程式,我經常需要遵循一個非同步任務與另一個,我的講話創建承諾鏈。鏈式的承諾將繼續沿移動通過的任務,即使在鏈中承諾之一返回一個錯誤。最佳做法是始終結束的諾言有對完成方法的調用鏈。完成的函數引發的任何錯誤的被抓在錯誤處理常式中的任何先前那語句。這意味著我不需要在鏈中定義錯誤函數為每個承諾。

即便如此,追蹤錯誤可以在很長的鏈子很困難,一旦他們被困在對 promise.done 的調用。鏈式的承諾可以包含多個任務,其中任何一個,可能會失敗。我可以設置一個中斷點在每一項任務,請參閱錯誤的彈出,但那會是非常耗費時間。

這裡是Visual Studio2013年哪裡來拯救。已升級 (Visual Studio2010 仲介紹) 任務視窗來處理非同步 JavaScript 以及調試。在任務視窗中,您可以查看所有的活動和已完成任務,在任何給定的點在您的應用程式代碼中。

為此下一個示例中,我會將新的一頁添加到解決方案,以證明此令人敬畏的工具。在解決方案中,我創建一個新的資料夾,在頁資料夾中調用 chainedAsync,然後添加一個新的頁面控制項命名為 chainAsync.html (其中創建 /pages/­chainedAsync/chainedAsync.html 和關聯的.js 和.css 檔)。

在 chainedAsync.html,插入以下標記內 < 節 > 標籤:

<!-- ERROR:Clicking this button starts a chain reaction with an error.
-->
<p><button id="startChain">Start the error chain</button></p>
<p id="output"></p>

在 chainedAsync.js,添加中所示的事件處理常式圖 7到準備好的方法,以在頁面的 startChain 按鈕的 click 事件。

圖 7 的 chainedAsync.js 中的 PageControl.ready 函數的內容

startChain.addEventListener("click", function () {
  goodPromise().
then(function () {
        return goodPromise();
    }).
then(function () {
        return badPromise();
    }).
then(function () {
        return goodPromise();
    }).
done(function () {
        // This *shouldn't* get called
    },
      function (err) {
          document.getElementById('output').innerText = err.toString();
    });
});

最後,我定義的函數 goodPromise 和 badPromise 中所示圖 8,chainAsync.js,這樣他們就可在 PageControl 的方法內。

圖 8 的 goodPromise 和 badPromise 函式定義在 chainAsync.js 中的

function goodPromise() {
  return new WinJS.Promise(function (comp, err, prog) {
    try {
      comp();
    } catch (ex) {
      err(ex)
    }
  });
}
// ERROR: This returns an errored-out promise.
function badPromise() {
  return WinJS.Promise.wrapError("I broke my promise :(");
}

我再次運行示例,導航到"Chained 非同步"頁面,,然後按一下"啟動錯誤鏈"。後一種短等待消息"我打破了我的諾言: ("將顯示在按鈕下方。

現在我需要追蹤該錯誤發生的位置,找出如何修復它。(很明顯,在這種矯揉造作情況,我知道確切地發生錯誤的位置。出於學習目的,我會忘記那 badPromise 為我鏈式承諾注入錯誤)。

找出哪裡的鏈式的承諾會出差錯,我要將中斷點放在錯誤處理常式定義在對的調用中做為 startChain 按鈕的 click 處理常式中所示圖 9


圖 9 在 chainedAsync.html 中的中斷點位置

我再次,運行相同的測試和程式執行的Visual Studio的歸來,已停止在中斷點上。下一步,打開任務視窗 (調試 |Windows |任務),看看哪些任務當前處於活動狀態。結果將顯示在圖 10


圖 10 在 2013Visual Studio中的任務視窗顯示錯誤

在第一,一點也不在此視窗中鶴立雞群造成錯誤。該視窗列出了五個任務,所有這些都被標記為活動的。當我仔細看看,不過,我看到活動的任務之一是排隊的諾言錯誤的計畫程式 — 看上去有前途 (請原諒在壞的雙關)。

(如果你想知道關於調度程式,我鼓勵您閱讀本系列中的下一篇文章哪裡,我將討論在 WinJS 中的新計畫程式 API。)

當我將我的滑鼠懸停在該行 (ID 120 在圖 10) 在任務視窗中,我會得到有針對性的查看呼叫堆疊的那任務。我看到幾個錯誤處理常式,而且,瞧,badPromise 是呼叫堆疊的開頭附近。當我按兩下該行時,Visual Studio把我帶引發錯誤的 badPromise 中的程式碼。在真實世界的情況下,我現在會診斷 badPromise 認識錯誤的原因。

WinJS 提供了幾個級別的應用程式,除了可靠的 try catch finally 塊中的錯誤處理。一個性能良好的應用程式應使用適當程度的錯誤處理,為使用者提供流暢的體驗。在本文中,我演示了如何將應用程式級、 頁級和導航級別的錯誤處理到一個應用程式。我還演示了如何使用Visual Studio2013年中一些新的工具來跟蹤錯誤在鏈上的承諾。

在本系列中的下一篇文章,我將探討一些使 Windows 存儲應用程式執行得更好的技術。我會檢查 Web 工人、 WinJS 2.0 中新的計畫程式 API 和 WinJS 2.0 中新的處理模式。

Eric Schmidt 是內容開發商在微軟 Windows 開發人員內容團隊中,寫關於 Windows 庫的 JavaScript (WinJS)。他曾在Microsoft Office司,在那裡興建了代碼示例用於為辦公平臺的應用程式。他花時間與他的家庭、 戲劇字串低音、 生成 HTML5 視頻遊戲和博客塑膠建材玩具 (historybricks.com)。

感謝以下 Microsoft 技術專家對本文的審閱:克賴希 Brockschmidt 和喬希 · 威廉姆斯
克賴希 Brockschmidt 是高級程式管理器在 Windows 生態系統團隊中,直接使用開發人員社區和關鍵合作夥伴構建 Windows 應用商店的應用程式。他是在 HTML、 CSS 和 JavaScript 程式設計 Windows 存儲應用 (現在在其第二版) 作者,有同感,其他的見解 HTTP://www.kraigbrockschmidt.com/blog

喬希 · 威廉姆斯是主要軟體發展工程師中鉛的 Windows 開發人員體驗團隊。他和他的團隊為 JavaScript (WinJS) 建立了 Windows 庫。