Skip to content

Instantly share code, notes, and snippets.

@m-abs
Last active September 6, 2018 14:33
Show Gist options
  • Save m-abs/7f5783a51cc733717750c9d444f2f1a5 to your computer and use it in GitHub Desktop.
Save m-abs/7f5783a51cc733717750c9d444f2f1a5 to your computer and use it in GitHub Desktop.
Use async/await with NativeScript
// this import should be first in order to load some required settings (like globals and reflect-metadata)
import { platformNativeScriptDynamic } from "nativescript-angular/platform";
import { AppModule } from "./app.module";
import './tslib.nativescript'; // <-- ADD THIS LINE
// A traditional NativeScript application starts by initializing global objects, setting up global CSS rules, creating, and navigating to the main page.
// Angular applications need to take care of their own initialization: modules, components, directives, routes, DI providers.
// A NativeScript Angular app needs to make both paradigms work together, so we provide a wrapper platform object, platformNativeScriptDynamic,
// that sets up a NativeScript application and can bootstrap the Angular framework.
platformNativeScriptDynamic().bootstrapModule(AppModule);
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at http://www.apache.org/licenses/LICENSE-2.0
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
// Copied from: https://github.com/Microsoft/tslib/blob/90b4e189558c86cd8779d396c69a8254ce913874/tslib.js#L90-L125
// tslint:disable
if (!('__awaiter' in global)) {
global['__awaiter'] = function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
}
if (!('__generator' in global)) {
global['__generator'] = function (thisArg, body) {
var _: any = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [0, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
}
@m-abs
Copy link
Author

m-abs commented Aug 1, 2017

Import first thing in your main.ts-file

Now you should be able to use async/await in your NativeScript-app.

@carrbrpoa
Copy link

carrbrpoa commented Aug 1, 2017

So, I created a file named tslib.nativescript.ts with the contents you provided in the app folder and tried to import in main.ts like this:

import * as AsyncUtils from "./tslib.nativescript";

But it tells me that file is not a module. Missed something?

Thanks!

@carrbrpoa
Copy link

Well, that seems to be some amateurism :)
Just copying and pasting the two if's to main.ts does the job when tns run android.
The problem is that it doesn't with npm run start-android-bundle. The first time I try to call something that calls an async, it throws JS: ERROR ReferenceError: __awaiter is not defined.
Any ideas about that?

@m-abs
Copy link
Author

m-abs commented Aug 3, 2017

@carrbrpoa
I've updated the gist with an example main.ts to show how to import it.

I've also create a demo-app repo:
https://github.com/m-abs/tns-async-await

@nickcabral
Copy link

@m-abs I was happy to find this! Just so I know in the future, what change in nativescript needs to take place for this to go away? I'm just curious what to watch for to know when I can pull this code out. Thanks!

@bradmartin
Copy link

Ran into this today and struggling on it myself.

@zoitsa
Copy link

zoitsa commented Oct 20, 2017

@m-abs @carrbrpoa thanks for sharing those updates. I was having the same problem and the updates fixed my android crash for a while, however, the same errors are back without me changing anything to the code. Anyone have any more answers on this? @bradmartin did you resolve the issue?

@zoitsa
Copy link

zoitsa commented Oct 21, 2017

Actually, I realized that the issue was because I had to turn my import helpers on in order to get my data to come through, which resulted in the crash. Any advice on this?

This is my tsconfig.json

{ "compilerOptions": { "module": "commonjs", "target": "es5", "experimentalDecorators": true, "emitDecoratorMetadata": true, "noEmitHelpers": true, "importHelpers": false, "noEmitOnError": true, "lib": [ "es6", "dom", "es2015.iterable" ], "baseUrl": ".", "paths": { "*": [ "./node_modules/tns-core-modules/*", "./node_modules/*" ] } }, "exclude": [ "node_modules", "platforms", "**/*.aot.ts" ] }

@nickcabral
Copy link

I've found that you don't need to define your own __awaiter if you target es2017. It took me a while to figure out why my app was crashing on android but not iOS; it turns out you simply can't have importHelpers set to true, which I had so that I didn't have to define my own __awaiter. If targeting es2017 causes any problems for me in the future, I'll just restore this awaiter code posted by @m-abs and target an earlier ecmascript version.

I have a thread on discourse about this which also includes the (cryptic) error that I was receiving when importHelpers was set to true: https://discourse.nativescript.org/t/error-trying-to-link-invalid-this-to-a-java-object-async-await-importhelpers/3222

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment