mirror of
https://github.com/modernw/App-Installer-For-Windows-8.x-Reset.git
synced 2026-04-11 17:57:19 +10:00
534 lines
17 KiB
JavaScript
534 lines
17 KiB
JavaScript
/// <reference path="//Microsoft.WinJS.2.0/js/base.js" />
|
||
(function(global) {
|
||
"use strict";
|
||
/**
|
||
* PromisePolyfill 构造函数。
|
||
*
|
||
* 模拟 WinJS.Promise 的构造形式:
|
||
* new PromisePolyfill(init, oncancel)
|
||
*
|
||
* @constructor
|
||
* @param {function(function(any):void,function(any):void,function(any):void):void} pfInit
|
||
* Promise 初始化函数。
|
||
* 该函数在 Promise 创建时立即执行,并接收三个回调:
|
||
* - complete(value) : 完成 Promise
|
||
* - error(reason) : 使 Promise 失败
|
||
* - progress(value) : 发送进度通知(当前实现为占位)
|
||
*
|
||
* @param {function():void} [pfOnCancel]
|
||
* Promise 取消回调。当调用 promise.cancel() 时执行。
|
||
*
|
||
* @example
|
||
* var p = new PromisePolyfill(
|
||
* function (complete, error, progress) {
|
||
* setTimeout(function () {
|
||
* complete("done");
|
||
* }, 1000);
|
||
* },
|
||
* function () {
|
||
* console.log("Promise canceled");
|
||
* }
|
||
* );
|
||
*/
|
||
function PromisePolyfill(pfInit, pfOnCancel) {
|
||
/// <param name="pfInit" type="Function">
|
||
/// Promise 初始化函数。
|
||
/// 形参签名:
|
||
/// function(
|
||
/// complete : function(any):void,
|
||
/// error : function(any):void,
|
||
/// progress : function(any):void
|
||
/// )
|
||
/// </param>
|
||
/// <param name="pfOnCancel" type="Function" optional="true">
|
||
/// Promise 取消回调函数。当 promise.cancel() 被调用时执行。
|
||
/// </param>
|
||
var swState = "pending"; // "fulfilled" | "rejected"
|
||
var vValue = undefined;
|
||
var aHandlers = [];
|
||
|
||
function invokeHandlers() {
|
||
if (swState === "pending") return;
|
||
for (var i = 0; i < aHandlers.length; i++) {
|
||
handle(aHandlers[i]);
|
||
}
|
||
aHandlers = [];
|
||
}
|
||
|
||
function handle(hHandler) {
|
||
if (swState === "pending") {
|
||
aHandlers.push(hHandler);
|
||
return;
|
||
}
|
||
|
||
var pfCallback = swState === "fulfilled" ?
|
||
hHandler.onFulfilled :
|
||
hHandler.onRejected;
|
||
|
||
if (!pfCallback) {
|
||
if (swState === "fulfilled") {
|
||
hHandler.resolve(vValue);
|
||
} else {
|
||
hHandler.reject(vValue);
|
||
}
|
||
return;
|
||
}
|
||
|
||
try {
|
||
var vResult = pfCallback(vValue);
|
||
hHandler.resolve(vResult);
|
||
} catch (ex) {
|
||
hHandler.reject(ex);
|
||
}
|
||
}
|
||
|
||
function resolve(vResult) {
|
||
try {
|
||
|
||
if (vResult === self)
|
||
throw new TypeError("A promise cannot be resolved with itself.");
|
||
|
||
if (vResult && (typeof vResult === "object" || typeof vResult === "function")) {
|
||
var pfThen = vResult.then;
|
||
if (typeof pfThen === "function") {
|
||
pfThen.call(vResult, resolve, reject);
|
||
return;
|
||
}
|
||
}
|
||
|
||
swState = "fulfilled";
|
||
vValue = vResult;
|
||
invokeHandlers();
|
||
|
||
} catch (ex) {
|
||
reject(ex);
|
||
}
|
||
}
|
||
|
||
function reject(vReason) {
|
||
swState = "rejected";
|
||
vValue = vReason;
|
||
|
||
if (typeof PromisePolyfill.onerror === "function") {
|
||
PromisePolyfill.onerror(vReason);
|
||
}
|
||
|
||
invokeHandlers();
|
||
}
|
||
|
||
// WinJS Promise progress(当前仅占位)
|
||
function progress(vProgress) {
|
||
// 当前 polyfill 未实现 progress 传播
|
||
}
|
||
|
||
var self = this;
|
||
|
||
try {
|
||
if (typeof pfInit === "function") {
|
||
pfInit(resolve, reject, progress);
|
||
}
|
||
} catch (ex) {
|
||
reject(ex);
|
||
}
|
||
|
||
this.then = function(pfOnFulfilled, pfOnRejected) {
|
||
|
||
return new PromisePolyfill(function(resolve, reject) {
|
||
|
||
handle({
|
||
onFulfilled: pfOnFulfilled,
|
||
onRejected: pfOnRejected,
|
||
resolve: resolve,
|
||
reject: reject
|
||
});
|
||
|
||
});
|
||
|
||
};
|
||
|
||
this["catch"] = function(pfOnRejected) {
|
||
return this.then(null, pfOnRejected);
|
||
};
|
||
|
||
this.done = function(pfOnFulfilled, pfOnRejected) {
|
||
|
||
this.then(pfOnFulfilled, pfOnRejected)["catch"](function(ex) {
|
||
|
||
setTimeout(function() {
|
||
throw ex;
|
||
}, 0);
|
||
|
||
});
|
||
|
||
};
|
||
|
||
this.cancel = function() {
|
||
|
||
if (pfOnCancel) {
|
||
try {
|
||
pfOnCancel();
|
||
} catch (ex) {}
|
||
}
|
||
|
||
reject(new Error("Promise was canceled"));
|
||
|
||
};
|
||
|
||
this._oncancel = pfOnCancel;
|
||
this._state = swState;
|
||
this._value = vValue;
|
||
}
|
||
/**
|
||
* 检查对象是否为 PromisePolyfill 实例
|
||
* @param {any} vObj 待检查对象
|
||
* @returns {boolean} 是否为 PromisePolyfill 实例
|
||
*/
|
||
PromisePolyfill.is = function(vObj) {
|
||
return vObj instanceof PromisePolyfill;
|
||
};
|
||
/**
|
||
* 创建一个已完成的 PromisePolyfill
|
||
* @param {any} vValue 要返回的值
|
||
* @returns {PromisePolyfill} 已完成的 PromisePolyfill
|
||
*/
|
||
PromisePolyfill.resolve = function(vValue) {
|
||
return new PromisePolyfill(function(resolve) { resolve(vValue); });
|
||
};
|
||
/**
|
||
* 创建一个已拒绝的 PromisePolyfill
|
||
* @param {any} vReason 拒绝原因
|
||
* @returns {PromisePolyfill} 已拒绝的 PromisePolyfill
|
||
*/
|
||
PromisePolyfill.reject = function(vReason) {
|
||
return new PromisePolyfill(function(resolve, reject) { reject(vReason); });
|
||
};
|
||
/**
|
||
* 等待所有 Promise 完成
|
||
* @param {Array<PromisePolyfill|any>} aPromises 待处理的 Promise 或普通值数组
|
||
* @returns {PromisePolyfill<Array<any>>} 返回包含所有结果的 Promise
|
||
*/
|
||
PromisePolyfill.all = function(aPromises) {
|
||
return new PromisePolyfill(function(resolve, reject) {
|
||
var nRemaining = aPromises.length;
|
||
var aResults = new Array(nRemaining);
|
||
if (nRemaining === 0) resolve([]);
|
||
|
||
function resolver(iIndex) {
|
||
return function(vValue) {
|
||
aResults[iIndex] = vValue;
|
||
nRemaining--;
|
||
if (nRemaining === 0) resolve(aResults);
|
||
};
|
||
}
|
||
for (var i = 0; i < aPromises.length; i++) {
|
||
PromisePolyfill.resolve(aPromises[i]).then(resolver(i), reject);
|
||
}
|
||
});
|
||
};
|
||
/**
|
||
* 竞速 Promise,谁先完成就返回谁的结果
|
||
* @param {Array<PromisePolyfill|any>} aPromises 待处理的 Promise 或普通值数组
|
||
* @returns {PromisePolyfill<any>} 最先完成的 Promise 的值
|
||
*/
|
||
PromisePolyfill.race = function(aPromises) {
|
||
return new PromisePolyfill(function(resolve, reject) {
|
||
for (var i = 0; i < aPromises.length; i++) {
|
||
PromisePolyfill.resolve(aPromises[i]).then(resolve, reject);
|
||
}
|
||
});
|
||
};
|
||
/**
|
||
* Promise join,同 all
|
||
* @param {Array<PromisePolyfill|any>} aPromises 待处理的 Promise 或普通值数组
|
||
* @returns {PromisePolyfill<Array<any>>} 返回包含所有结果的 Promise
|
||
*/
|
||
PromisePolyfill.join = function(aPromises) {
|
||
return PromisePolyfill.all(aPromises);
|
||
};
|
||
/**
|
||
* 任意 Promise 完成即返回
|
||
* @param {Array<PromisePolyfill|any>} aPromises 待处理的 Promise 或普通值数组
|
||
* @returns {PromisePolyfill<any>} 最先完成的 Promise 的值,若都失败则 reject 一个错误数组
|
||
*/
|
||
PromisePolyfill.any = function(aPromises) {
|
||
return new PromisePolyfill(function(resolve, reject) {
|
||
var nRemaining = aPromises.length;
|
||
var aErrors = new Array(nRemaining);
|
||
if (nRemaining === 0) reject(new Error("No promises provided."));
|
||
|
||
function resolver(vValue) { resolve(vValue); }
|
||
|
||
function rejecter(iIndex) {
|
||
return function(ex) {
|
||
aErrors[iIndex] = ex;
|
||
nRemaining--;
|
||
if (nRemaining === 0) reject(aErrors);
|
||
};
|
||
}
|
||
for (var i = 0; i < aPromises.length; i++) {
|
||
PromisePolyfill.resolve(aPromises[i]).then(resolver, rejecter(i));
|
||
}
|
||
});
|
||
};
|
||
/**
|
||
* 给 Promise 添加超时处理
|
||
* @param {PromisePolyfill|any} pPromise 要处理的 Promise
|
||
* @param {number} nMilliseconds 超时时间(毫秒)
|
||
* @returns {PromisePolyfill<any>} 超时或原 Promise 完成后 resolve/reject
|
||
*/
|
||
PromisePolyfill.timeout = function(pPromise, nMilliseconds) {
|
||
return new PromisePolyfill(function(resolve, reject) {
|
||
var hTimer = setTimeout(function() {
|
||
reject(new Error("Promise timed out after " + nMilliseconds + "ms"));
|
||
}, nMilliseconds);
|
||
PromisePolyfill.resolve(pPromise).then(function(vValue) {
|
||
clearTimeout(hTimer);
|
||
resolve(vValue);
|
||
}, function(ex) {
|
||
clearTimeout(hTimer);
|
||
reject(ex);
|
||
});
|
||
});
|
||
};
|
||
PromisePolyfill.as = function(vValue) {
|
||
return PromisePolyfill.resolve(vValue);
|
||
};
|
||
PromisePolyfill.wrap = function(vValue) {
|
||
return PromisePolyfill.resolve(vValue);
|
||
};
|
||
PromisePolyfill.wrapError = function(vError) {
|
||
return PromisePolyfill.reject(vError);
|
||
};
|
||
/**
|
||
* 将数组的每个值依次执行回调
|
||
* @param {Array<any>} aValues 数组
|
||
* @param {function(any, number): any | PromisePolyfill<any>} pfCallback 回调函数
|
||
* @returns {PromisePolyfill<Array<any>>} 所有回调完成的结果数组
|
||
*/
|
||
PromisePolyfill.thenEach = function(aValues, pfCallback) {
|
||
var aPromises = [];
|
||
for (var i = 0; i < aValues.length; i++) {
|
||
aPromises.push(PromisePolyfill.resolve(aValues[i]).then(pfCallback));
|
||
}
|
||
return PromisePolyfill.all(aPromises);
|
||
};
|
||
var hListeners = {};
|
||
/**
|
||
* 全局事件注册
|
||
* @param {string} sType 事件类型
|
||
* @param {function(any):void} pfHandler 回调函数
|
||
*/
|
||
PromisePolyfill.addEventListener = function(sType, pfHandler) {
|
||
if (!hListeners[sType]) hListeners[sType] = [];
|
||
hListeners[sType].push(pfHandler);
|
||
};
|
||
/**
|
||
* 全局事件移除
|
||
* @param {string} sType 事件类型
|
||
* @param {function(any):void} pfHandler 回调函数
|
||
*/
|
||
PromisePolyfill.removeEventListener = function(sType, pfHandler) {
|
||
if (!hListeners[sType]) return;
|
||
var aList = hListeners[sType];
|
||
for (var i = 0; i < aList.length; i++) {
|
||
if (aList[i] === pfHandler) {
|
||
aList.splice(i, 1);
|
||
break;
|
||
}
|
||
}
|
||
};
|
||
/**
|
||
* 全局事件派发
|
||
* @param {string} sType 事件类型
|
||
* @param {any} vDetail 事件详情
|
||
*/
|
||
PromisePolyfill.dispatchEvent = function(sType, vDetail) {
|
||
if (!hListeners[sType]) return;
|
||
var aList = hListeners[sType].slice();
|
||
for (var i = 0; i < aList.length; i++) {
|
||
try { aList[i](vDetail); } catch (ex) {}
|
||
}
|
||
};
|
||
PromisePolyfill.supportedForProcessing = true;
|
||
PromisePolyfill.onerror = null;
|
||
/**
|
||
* 创建一个在指定毫秒数后完成的 Promise。
|
||
*
|
||
* @param {number} nMilliseconds
|
||
* 延迟时间(毫秒)。
|
||
*
|
||
* @returns {PromisePolyfill}
|
||
* 返回 Promise,在延迟结束后完成。
|
||
*
|
||
* @example
|
||
* WinJS.Promise.delay(500).then(function () {
|
||
* console.log("500ms elapsed");
|
||
* });
|
||
*/
|
||
PromisePolyfill.delay = function(nMilliseconds) {
|
||
/// <param name="nMilliseconds" type="Number">
|
||
/// 延迟时间(毫秒)。
|
||
/// </param>
|
||
/// <returns type="PromisePolyfill"/>
|
||
var hTimer = null;
|
||
return new PromisePolyfill(
|
||
function(complete, error, progress) {
|
||
hTimer = setTimeout(function() {
|
||
complete();
|
||
}, nMilliseconds);
|
||
},
|
||
function() {
|
||
if (hTimer !== null) {
|
||
clearTimeout(hTimer);
|
||
hTimer = null;
|
||
}
|
||
}
|
||
);
|
||
};
|
||
/**
|
||
* 创建一个循环执行的 Promise,类似 setInterval。
|
||
*
|
||
* 该 Promise 不会自动完成,除非:
|
||
* 1. 调用 promise.cancel()
|
||
* 2. callback 抛出异常
|
||
*
|
||
* @param {function(): (any|PromisePolyfill|WinJS.Promise)} pfCallback
|
||
* 每次循环执行的回调函数。可以返回 Promise。
|
||
*
|
||
* @param {number} nDelay
|
||
* 每次执行之间的间隔时间(毫秒)。
|
||
*
|
||
* @returns {PromisePolyfill}
|
||
* 返回 Promise 对象,可通过 cancel() 停止循环。
|
||
*
|
||
* @example
|
||
* var p = WinJS.Promise.interval(function () {
|
||
* console.log("tick");
|
||
* }, 1000);
|
||
*
|
||
* setTimeout(function () {
|
||
* p.cancel();
|
||
* }, 5000);
|
||
*/
|
||
PromisePolyfill.interval = function(pfCallback, nDelay) {
|
||
|
||
/// <param name="pfCallback" type="Function">
|
||
/// 每次间隔执行的函数。可以返回 Promise。
|
||
/// </param>
|
||
/// <param name="nDelay" type="Number">
|
||
/// 执行间隔(毫秒)。
|
||
/// </param>
|
||
/// <returns type="PromisePolyfill"/>
|
||
|
||
var bCanceled = false;
|
||
|
||
return new PromisePolyfill(
|
||
|
||
function(complete, error, progress) {
|
||
|
||
function loop() {
|
||
|
||
if (bCanceled) {
|
||
complete();
|
||
return;
|
||
}
|
||
|
||
try {
|
||
|
||
var vResult = pfCallback();
|
||
|
||
if (vResult && typeof vResult.then === "function") {
|
||
|
||
vResult.then(waitNext, error);
|
||
|
||
} else {
|
||
|
||
waitNext();
|
||
|
||
}
|
||
|
||
} catch (ex) {
|
||
|
||
error(ex);
|
||
|
||
}
|
||
|
||
}
|
||
|
||
function waitNext() {
|
||
|
||
if (bCanceled) {
|
||
complete();
|
||
return;
|
||
}
|
||
|
||
setTimeout(loop, nDelay);
|
||
|
||
}
|
||
|
||
loop();
|
||
|
||
},
|
||
|
||
function() {
|
||
|
||
bCanceled = true;
|
||
|
||
}
|
||
|
||
);
|
||
|
||
};
|
||
if (typeof global.Promise !== "undefined") {
|
||
global.Promise.delay = PromisePolyfill.delay;
|
||
global.Promise.interval = PromisePolyfill.interval;
|
||
}
|
||
if (typeof global.WinJS !== "undefined" && typeof global.WinJS.Promise !== "undefined") {
|
||
global.WinJS.Promise.delay = PromisePolyfill.delay;
|
||
global.WinJS.Promise.interval = PromisePolyfill.interval;
|
||
}
|
||
if (typeof global.Promise !== "undefined") {
|
||
var p = global.Promise;
|
||
if (!p.join) p.join = p.all;
|
||
if (!p.any) p.any = PromisePolyfill.any;
|
||
if (!p.timeout) p.timeout = PromisePolyfill.timeout;
|
||
if (!p.as) p.as = p.resolve;
|
||
if (!p.wrap) p.wrap = p.resolve;
|
||
if (!p.wrapError) p.wrapError = p.reject;
|
||
if (!p.thenEach) p.thenEach = PromisePolyfill.thenEach;
|
||
if (!p.is) p.is = function(vObj) { return vObj instanceof p; };
|
||
if (!p.supportedForProcessing) p.supportedForProcessing = true;
|
||
if (!p.addEventListener) p.addEventListener = PromisePolyfill.addEventListener;
|
||
if (!p.removeEventListener) p.removeEventListener = PromisePolyfill.removeEventListener;
|
||
if (!p.dispatchEvent) p.dispatchEvent = PromisePolyfill.dispatchEvent;
|
||
if (!p.onerror) p.onerror = null;
|
||
if (typeof p.prototype.then !== "function") {
|
||
p.prototype.then = function(onFulfilled, onRejected) {
|
||
return new p(function(resolve, reject) {
|
||
this.then(resolve, reject);
|
||
}).then(onFulfilled, onRejected);
|
||
};
|
||
}
|
||
if (typeof p.prototype.done !== "function") {
|
||
p.prototype.done = function(onFulfilled, onRejected) {
|
||
this.then(onFulfilled, onRejected)["catch"](function(ex) {
|
||
setTimeout(function() {
|
||
throw ex;
|
||
}, 0);
|
||
});
|
||
};
|
||
}
|
||
}
|
||
if (typeof global.WinJS !== "undefined" && typeof global.WinJS.Promise !== "undefined") {
|
||
var wp = global.WinJS.Promise;
|
||
if (!wp.resolve) wp.resolve = function(vValue) { return new wp(function(c) { c(vValue); }); };
|
||
if (!wp.reject) wp.reject = function(vReason) { return new wp(function(c, e) { e(vReason); }); };
|
||
if (!wp.all) wp.all = function(aPromises) { return wp.join(aPromises); };
|
||
if (!wp.race) wp.race = PromisePolyfill.race;
|
||
global.Promise = wp;
|
||
if (typeof global.Promise === "undefined") global.Promise = wp;
|
||
}
|
||
if (typeof global.Promise === "undefined" && typeof global.WinJS === "undefined") {
|
||
global.Promise = PromisePolyfill;
|
||
}
|
||
})(this); |