Skip to content
This repository was archived by the owner on Feb 26, 2024. It is now read-only.

Commit 4b52ea0

Browse files
committed
feat(asynchooks): use asynchooks to handle native async/await
1 parent 1741e70 commit 4b52ea0

10 files changed

+153
-261
lines changed

gulpfile.js

+9-8
Original file line numberDiff line numberDiff line change
@@ -314,17 +314,10 @@ gulp.task('build', [
314314
'build/closure.js'
315315
]);
316316

317-
gulp.task('test/node2017', ['compile-node-es2017'], function(cb) {
318-
var testAsyncPromise = require('./build/test/node_async').testAsyncPromise;
319-
testAsyncPromise();
320-
});
321-
322-
gulp.task('test/node', ['compile-node'], function(cb) {
317+
function runJasmineTest(specFiles, cb) {
323318
var JasmineRunner = require('jasmine');
324319
var jrunner = new JasmineRunner();
325320

326-
var specFiles = ['build/test/node_entry_point.js'];
327-
328321
jrunner.configureDefaultReporter({showColors: true});
329322

330323
jrunner.onComplete(function(passed) {
@@ -345,6 +338,14 @@ gulp.task('test/node', ['compile-node'], function(cb) {
345338
jrunner.specDir = '';
346339
jrunner.addSpecFiles(specFiles);
347340
jrunner.execute();
341+
}
342+
343+
gulp.task('test/node2017', ['compile-node-es2017'], function(cb) {
344+
runJasmineTest(['build/test/node_entry_point_es2017.js'], cb);
345+
});
346+
347+
gulp.task('test/node', ['compile-node'], function(cb) {
348+
runJasmineTest(['build/test/node_entry_point.js'], cb);
348349
});
349350

350351
// Check the coding standards and programming errors

lib/node/async_hooks_promise.ts

-64
This file was deleted.

lib/node/async_promise.ts

+4-15
Original file line numberDiff line numberDiff line change
@@ -41,26 +41,18 @@ Zone.__load_patch('node_async_hooks_promise', (global: any, Zone: ZoneType, api:
4141
const originalThen = promise.then;
4242

4343
const zone = Zone.current;
44-
if (zone.name === 'promise') {
45-
print('init promise', id.toString());
46-
}
4744
if (!zone.parent) {
48-
print('root zone');
4945
return;
5046
}
5147
const currentAsyncContext: any = {};
5248
currentAsyncContext.id = id;
5349
currentAsyncContext.zone = zone;
5450
idPromise[id] = currentAsyncContext;
5551
promise.then = function(onResolve: any, onReject: any) {
56-
const wrapped = new Promise((resolve, reject) => {
57-
originalThen.call(this, resolve, reject);
58-
});
59-
if (zone) {
60-
(wrapped as any).zone = zone;
61-
}
62-
return zone.run(() => {
63-
return wrapped.then(onResolve, onReject);
52+
const task = zone.scheduleMicroTask(PROMISE_PROVIDER, noop, null, noop);
53+
process.nextTick(() => {
54+
task.zone.runTask(task, null, null);
55+
originalThen.call(this, onResolve, onReject);
6456
});
6557
};
6658
}
@@ -69,22 +61,19 @@ Zone.__load_patch('node_async_hooks_promise', (global: any, Zone: ZoneType, api:
6961
function before(id: number) {
7062
const currentAsyncContext = idPromise[id];
7163
if (currentAsyncContext) {
72-
print('before ' + id, currentAsyncContext.zone.name);
7364
api.setAsyncContext(currentAsyncContext);
7465
}
7566
}
7667

7768
function after(id: number) {
7869
const currentAsyncContext = idPromise[id];
7970
if (currentAsyncContext) {
80-
print('after ' + id, currentAsyncContext.zone.name);
8171
idPromise[id] = null;
8272
api.setAsyncContext(null);
8373
}
8474
}
8575

8676
function destroy(id: number) {
87-
print('destroy ' + id);
8877
}
8978

9079
async_hooks.createHook({init, before, after, destroy}).enable();

test/asynchooks/await.spec.ts

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/**
2+
* @license
3+
* Copyright Google Inc. All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
9+
describe('native async/await', function() {
10+
const log: string[] = [];
11+
const zone = Zone.current.fork({
12+
name: 'promise',
13+
onScheduleTask: (delegate: ZoneDelegate, curr: Zone, target: Zone, task: any) => {
14+
log.push('scheduleTask');
15+
return delegate.scheduleTask(target, task);
16+
},
17+
onInvokeTask: (delegate: ZoneDelegate, curr: Zone, target: Zone, task: any, applyThis: any,
18+
applyArgs: any) => {
19+
log.push('invokeTask');
20+
return delegate.invokeTask(target, task, applyThis, applyArgs);
21+
}
22+
});
23+
24+
it('should still in zone after await', function(done) {
25+
async function asyncOutside() {
26+
return 'asyncOutside';
27+
}
28+
29+
const neverResolved = new Promise(() => {});
30+
const waitForNever = new Promise((res, _) => {
31+
res(neverResolved);
32+
});
33+
34+
async function getNever() {
35+
return waitForNever;
36+
};
37+
38+
zone.run(async() => {
39+
const outside = await asyncOutside();
40+
expect(outside).toEqual('asyncOutside');
41+
expect(Zone.current.name).toEqual(zone.name);
42+
43+
async function asyncInside() {
44+
return 'asyncInside';
45+
};
46+
47+
const inside = await asyncInside();
48+
expect(inside).toEqual('asyncInside');
49+
expect(Zone.current.name).toEqual(zone.name);
50+
51+
expect(log).toEqual(['scheduleTask', 'invokeTask', 'scheduleTask', 'invokeTask']);
52+
53+
done();
54+
});
55+
});
56+
});

0 commit comments

Comments
 (0)