使用Typescript ansyc 编写微信小程序文件上传

时间:2022-01-18 16:43:14

微信小程序的 js 代码是 ES6,当前 TypeScript 的 ansyc 可以编译为 ES3/ES5,因此可以用 ansyc 来编写。

使用 ansyc 来编写,最大的好处是代码可读性,相对于ES5的更容易阅读。另外,TypeScript 强制类型检查,使得代码的出错概率减少。

下面是用 ansyc 和 ES5 的代码对比:

    // define voice upload function
const uploadVoice = function (next) {
if (!that.data.voice) {
//console.log('no voice to upload');
next(true);
return;
}
const uploadTask = wx.uploadFile({
url: app.globalData.serverOrigin + '/resource?duration=' + that.data.voiceDuration + '&token=' + app.getToken(),
filePath: that.data.voice.tempFilePath,
name: 'resourceFile',
success: function (res) {
//console.log(res);
let resdata = JSON.parse(res.data);
postData.voiceID = resdata.Id;
next(true);
},
fail: function (e) {
console.log('voice upload err:');
console.log(e);
next(false);
}
});
uploadTask.onProgressUpdate(res => {
//console.log('voice file: %d%%', res.progress);
updateProgress(that.data.images.length, res.progress);
});
};
// define after voice uploaded process function
const uploadVoiceNext = function (isSuccess) {
if (isSuccess) {
doPost();
} else {
cancelPost();
}
};
// define after image uploaded process function
const uploadImageNext = function (isSuccess) {
if (isSuccess) {
uploadVoice(uploadVoiceNext);
} else {
cancelPost();
}
};
// define image upload process funciton
const uploadImag = function (i, next) {
if (i == that.data.images.length) {
//console.log('no more image to upload');
next(true);
return;
}
const uploadTask = wx.uploadFile({
url: app.globalData.serverOrigin + '/resource?token=' + app.getToken(),
filePath: that.data.images[i].path,
name: 'resourceFile',
success: function (res) {
//console.log(res);
let resdata = JSON.parse(res.data);
postData.resourceIDs.push(resdata.Id);
if (i < that.data.images.length) {
uploadImag(i + 1, next);
} else {
next(true);
}
},
fail: function (e) {
console.log('image upload err:');
console.log(e);
next(false);
}
});
uploadTask.onProgressUpdate(res => {
//console.log('image file %d: %d%%', i + 1, res.progress);
updateProgress(i, res.progress);
});
};

// begin do upload image one by one and than upload voice by called with uploadimageNext
uploadImag(0, uploadImageNext);
}

使用 ansyc 的 ts 代码:

function uploadFile(url: string, filePath: string, progress?: (progress: number) => never):Promise<number> {    return new Promise<number>((resolve, reject) => {        const uploadTask = wx.uploadFile({            url: url,            filePath: filePath,            name: 'resourceFile',            success: (res:{data:{Id:number,errMsg?:string},errMsg:string,statusCode:number}) => {                if (res.data.errMsg) throw new Error(`upload file[${filePath}] occurs error:${res.errMsg}`)                resolve(res.data.Id)},            fail: e => reject(e)        });        if (progress){        uploadTask.onProgressUpdate =            (res: { progress: number; totalBytesSent: number; totalBytesExpectedToSend: number; }): never => {                return progress(res.progress)            }        }    });}async function post2sever(page: IPage) {    try {        // upload images        let fileIDs:number[] = []        for (let img of page.data.images) {            let id = await uploadFile(Comm.getRequestUrl('/resource'), img)            fileIDs.push(id);        }        // upload voice        let voiceID:number        if (page.data.voice){            voiceID = await uploadFile(                Comm.getRequestUrl(`/resource?duration=${page.data.voice.duration}`), page.data.voice.path)        }        // post    } catch{    }}

注:使用的微信 API d.ts 来自:https://github.com/Emeryao/typed-we-app

      编译成 ES5 时,需要设置 tsconfig.json,添加 lib 内容(由于使用了Object.assign 函数,我加的 lib 是 es6,dom,es2015.promise)

参考:https://www.tslang.cn/docs/release-notes/typescript-2.1.html

低版本异步函数

该特性在TypeScript 2.1之前就已经支持了,但是只能编译为ES6或者ES2015。TypeScript 2.1使其该特性可以在ES3和ES5运行时上使用,这意味着无论您使用什么环境,都可以使用它。

注:首先,我们需要确保我们的运行时提供全局的ECMAScript兼容性Promise。这可能需要获取Promisepolyfill,或者依赖运行时的版本。我们还需要通过设置lib编译参数,比如"dom","es2015""dom","es2015.promise","es5"来确保TypeScript知道Promise可用。

示例

tsconfig.json
{ "compilerOptions": { "lib": ["dom", "es2015.promise", "es5"] }}