Update and fix bugs.

This commit is contained in:
Bruce
2026-03-25 23:34:36 +08:00
parent ca0b7dbcbb
commit a3ff273405
51 changed files with 175860 additions and 28 deletions

View File

@@ -1,11 +1,51 @@
/// <reference path="//Microsoft.WinJS.2.0/js/base.js" />
(function(global) {
"use strict";
function PromisePolyfill(pfExecutor) {
/**
* 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 = [];
var pfOnCancel = null;
function invokeHandlers() {
if (swState === "pending") return;
@@ -20,7 +60,11 @@
aHandlers.push(hHandler);
return;
}
var pfCallback = swState === "fulfilled" ? hHandler.onFulfilled : hHandler.onRejected;
var pfCallback = swState === "fulfilled" ?
hHandler.onFulfilled :
hHandler.onRejected;
if (!pfCallback) {
if (swState === "fulfilled") {
hHandler.resolve(vValue);
@@ -29,6 +73,7 @@
}
return;
}
try {
var vResult = pfCallback(vValue);
hHandler.resolve(vResult);
@@ -39,7 +84,10 @@
function resolve(vResult) {
try {
if (vResult === self) throw new TypeError("A promise cannot be resolved with itself.");
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") {
@@ -47,9 +95,11 @@
return;
}
}
swState = "fulfilled";
vValue = vResult;
invokeHandlers();
} catch (ex) {
reject(ex);
}
@@ -58,56 +108,105 @@
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 {
pfExecutor(resolve, reject, function(pfCancel) {
pfOnCancel = pfCancel;
});
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);
setTimeout(function() {
throw ex;
}, 0);
});
};
this.cancel = function() {
if (pfOnCancel) {
try { pfOnCancel(); } catch (ex) {}
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;
@@ -126,6 +225,11 @@
}
});
};
/**
* 竞速 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++) {
@@ -133,9 +237,19 @@
}
});
};
/**
* 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;
@@ -156,6 +270,12 @@
}
});
};
/**
* 给 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() {
@@ -179,6 +299,12 @@
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++) {
@@ -187,10 +313,20 @@
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];
@@ -201,6 +337,11 @@
}
}
};
/**
* 全局事件派发
* @param {string} sType 事件类型
* @param {any} vDetail 事件详情
*/
PromisePolyfill.dispatchEvent = function(sType, vDetail) {
if (!hListeners[sType]) return;
var aList = hListeners[sType].slice();
@@ -210,6 +351,142 @@
};
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;