因为公司产品需要搞个Web App,但是又需要兼容IE7,这时候整个应用会非常复杂,尤其是在处理异步的时候,在我的选择中有两个方案
- callback方案
- async/await
经过衡量以后,决定使用async/await方案
配置typescript环境
$ mkdir typescript-async # 新建项目目录
$ cd typescript-async # 进入项目目录
$ npm init -y # 初始化项目
$ npm i webpack --save-dev # 安装webpack
$ npm i ts-loader --save-dev # 安装loader
$ npm i typescript --save-dev # 安装typescript编译器
$ npm i es3ify-webpack-plugin --save-dev
$ touch webpack.dev.js # 新建webpack配置文件
$ .\node_modules\.bin\tsc --init # 创建typescript配置文件
webpack.dev.js
改为如下
const path = require('path');
const es3ifyPlugin = require('es3ify-webpack-plugin');module.exports = {mode: 'development',entry: './src/index.ts',output: {path: path.resolve(__dirname, 'build'),filename: '[name].js',},module: {rules: [{test: /\.ts$/,use: ['ts-loader'],}],},resolve: {extensions: ['.ts'],},devtool: "source-map",plugins: [new es3ifyPlugin(),],
};
package.json
修改为如下
{// ..."scripts": {
- "test": "echo \"Error: no test specified\" && exit 1",
+ "start": "webpack --config webpack.dev.js"}// ...
}
tsconfig.json
修改为如下
{"compilerOptions": {// ...
- "target": "es5",
+ "target": "es3",// ...
- "strict": true,
+ "strict": false,// ...}
}
配置测试
$ mkdir src
$ touch src/index.ts # 新建文件
index.ts
改为如下
const log = (text: string) => console.log(text);for (let i = 0; i < 5; i++) {log(String(i));
}
编译源码
$ npm start
只要没有报错,就可以在看到build/main.js
文件,这个文件就是编译后的结果,那么typescript的编译环境就搭建好了
支持async、await
$ npm i es6-promise --save # 安装promise polyfill
webpack.dev.js
改为如下
module.exports = {// ...resolve: {
- extensions: ['.ts'],
+ extensions: ['.js', '.ts'],},// ...
};
tsconfig.json
修改为如下
{"compilerOptions": {// ...
+ "lib": [
+ "dom",
+ "es2015",
+ "scripthost"
+ ], // ...}
}
src/index.ts
改为如下
import "es6-promise/auto"; // 低版本浏览器支持promiseconst delay = (time: number) => new Promise(resolve => setTimeout(resolve, time));(async () => {await delay(1000);alert('done.');
})();
编译源码
$ npm start
编译成功,async/await在ES3的环境下可以使用了
优化helpers代码
什么是helpers代码?直接看例子,有以下代码
src/index.ts
改为如下
import "es6-promise/auto";
import delayA from "./a";
import delayB from "./b";const delay = (time: number) => new Promise(resolve => setTimeout(resolve, time));(async () => {await delay(1000);alert('1');await delayA(1000);alert('2');await delayB(1000);alert('3');
})();
src/a.ts
改为如下
const delay = (time: number) => new Promise(resolve => setTimeout(resolve, time));async function delayA(time: number) {await delay(time);
}export default delayA;
src/b.ts
改为如下
const delay = (time: number) => new Promise(resolve => setTimeout(resolve, time));async function delayB(time: number) {await delay(time);
}export default delayB;
编译源码
$ npm start
查看生成后的代码build/main.js
,会看到有以下部分
// 省略以上代码/************************************************************************/
/******/ ({/***/ "./src/a.ts":
/*!******************!*\!*** ./src/a.ts ***!\******************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {"use strict";var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {// ...省略
};
var __generator = (this && this.__generator) || function (thisArg, body) {// ...省略
};
exports.__esModule = true;
var delay = function (time) { return new Promise(function (resolve) { return setTimeout(resolve, time); }); };
function delayA(time) {return __awaiter(this, void 0, void 0, function () {return __generator(this, function (_a) {switch (_a.label) {case 0: return [4 /*yield*/, delay(time)];case 1:_a.sent();return [2 /*return*/];}});});
}
exports["default"] = delayA;/***/ }),/***/ "./src/b.ts":
/*!******************!*\!*** ./src/b.ts ***!\******************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {"use strict";var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {// ...省略
};
var __generator = (this && this.__generator) || function (thisArg, body) {// ...省略
};
exports.__esModule = true;
var delay = function (time) { return new Promise(function (resolve) { return setTimeout(resolve, time); }); };
function delayB(time) {return __awaiter(this, void 0, void 0, function () {return __generator(this, function (_a) {switch (_a.label) {case 0: return [4 /*yield*/, delay(time)];case 1:_a.sent();return [2 /*return*/];}});});
}
exports["default"] = delayB;/***/ }),/***/ "./src/index.ts":
/*!**********************!*\!*** ./src/index.ts ***!\**********************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {"use strict";var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {// ...省略
};
var __generator = (this && this.__generator) || function (thisArg, body) {// ...省略
};
var __importDefault = (this && this.__importDefault) || function (mod) {return (mod && mod.__esModule) ? mod : { "default": mod };
};
var _this = this;
exports.__esModule = true;
__webpack_require__(/*! es6-promise/auto */ "./node_modules/es6-promise/auto.js");
var a_1 = __importDefault(__webpack_require__(/*! ./a */ "./src/a.ts"));
var b_1 = __importDefault(__webpack_require__(/*! ./b */ "./src/b.ts"));
var delay = function (time) { return new Promise(function (resolve) { return setTimeout(resolve, time); }); };
(function () { return __awaiter(_this, void 0, void 0, function () {return __generator(this, function (_a) {switch (_a.label) {case 0: return [4 /*yield*/, delay(1000)];case 1:_a.sent();alert('1');return [4 /*yield*/, a_1["default"](1000)];case 2:_a.sent();alert('2');return [4 /*yield*/, b_1["default"](1000)];case 3:_a.sent();alert('3');return [2 /*return*/];}});
}); })();/***/ })/******/ });
//# sourceMappingURL=main.js.map
可以看到大量的重复的__awaiter
、__generator
代码,这个就是helpers代码,我们需要去掉重复的代码,处理的方式有以下两种
方法1:importHelpers开关
$ npm i tslib --save # 安装tslib
tsconfig.json
修改为如下
{"compilerOptions": {// ...
+ "importHelpers": true,// ...}
}
注:上面这种方式需要支持Object.defineProperty
这个方法,但是ES3环境不支持,所以ES3环境下不能用这个方式
方法2:noEmitHelpers开关
$ npm i tslib --save # 安装tslib
tsconfig.json
修改为如下
{"compilerOptions": {// ...
+ "noEmitHelpers": true,// ...}
}
src/index.ts
改为如下
import "es6-promise/auto";
+ import 'tslib/tslib';
// ...
编译源码
$ npm start
查看生成后的代码build/main.js
,可以看到重复的部分没有了
以上就是整个在ES3环境下使用async/await的方法
typescript在ES3(IE7)环境下使用async、await