自Promise被纳入ECMAScript6标准后,各大浏览器几乎都实现了Promise标准。
以下是ecmascript6里promise的典型用法,为了解决一个线程的任务完成后,再去执行另一个任务。
var promise = new Promise(function(resolve, reject) { $.ajax({ success: function() { resolve(); }, failure: function() { reject(); } }) }); promise.then(function() { //调用了resolve或者reject之后 });
Java实现Promise相比较ECMAScript6来说,有些不同。
Javascript不管怎么样都是单线程的,即使ajax在浏览器内核层面表现出多线程,但是执行到js端还是单线程的。而在java上实现promise机制则复杂的多。具体表现在:
1)即使在上一个线程执行任务后,下一个任务可以在同一个线程中执行,但是加入任务的操作不得不是同步的
Netty4源码:io.netty.util.concurrent.DefaultPromise
@Override public Promise<V> addListener(GenericFutureListener<? extends Future<? super V>> listener) { if (listener == null) { throw new NullPointerException("listener"); } if (isDone()) { notifyLateListener(listener); return this; } //加入时必须同步 synchronized (this) { if (!isDone()) { if (listeners == null) { listeners = listener; } else { if (listeners instanceof DefaultFutureListeners) { ((DefaultFutureListeners) listeners).add(listener); } else { final GenericFutureListener<? extends Future<V>> firstListener = (GenericFutureListener<? extends Future<V>>) listeners; listeners = new DefaultFutureListeners(firstListener, listener); } } return this; } } notifyLateListener(listener); return this; }
2)在多个平行任务(线程)结束后,再去执行一个任务的case (Promise.all)的时候,判断任务是否结束的计数操作也不得不是同步的。
Netty源码:io.netty.channel.group.DefaultChannelGroupFuture
private final ChannelFutureListener childListener = new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture future) throws Exception { boolean success = future.isSuccess(); boolean callSetDone; // 判断所有的task是否已经结束也必须同步 synchronized (DefaultChannelGroupFuture.this) { if (success) { successCount ++; } else { failureCount ++; } callSetDone = successCount + failureCount == futures.size(); assert successCount + failureCount <= futures.size(); } if (callSetDone) { if (failureCount > 0) { List<Map.Entry<Channel, Throwable>> failed = new ArrayList<Map.Entry<Channel, Throwable>>(failureCount); for (ChannelFuture f: futures.values()) { if (!f.isSuccess()) { failed.add(new DefaultEntry<Channel, Throwable>(f.channel(), f.cause())); } } setFailure0(new ChannelGroupException(failed)); } else { setSuccess0(); } } } };
相关推荐
回调函数、Promise和async/await提供了处理异步操作的方法,理解和掌握这些,可以有效解决JavaScript中的“回调地狱”问题。 除此之外,熟悉JavaScript的内置对象和方法,如Array的迭代方法(`map()`, `filter()`, ...
3. **编码实现**:使用Java和微信小程序开发工具进行编码,搭建服务器环境。 4. **测试调试**:进行单元测试和整体功能测试,修复问题。 5. **上线部署**:通过微信开发者工具提交审核,完成上线。 五、技术难点与...
JavaScript源码大全是一本专为Java程序员或对编程有浓厚兴趣的读者设计的书籍,它深入探讨了JavaScript这门广泛应用于网页开发、浏览器交互及现代Web应用的核心语言。JavaScript不仅在前端开发中扮演着重要角色,...
异步编程是JavaScript中的难点,主要涉及回调函数、Promise、async/await。回调函数是处理异步操作的原始方式,但可能导致“回调地狱”问题。Promise解决了这一问题,提供了一种链式处理异步操作的方法。async/await...
在JavaScript、Python、Java等语言中,异步操作通常通过回调函数、Promise、async/await等方式实现。 2. **异步功能的集成测试难点**: - **时间依赖性**:异步操作的结果可能会在不确定的时间点到达,这增加了...
6. **JavaScript的挑战**:JavaScript的全局作用域、异步编程模型(回调地狱、Promise、async/await)、以及对闭包和原型链的理解,都是开发者常常遇到的难点。 7. **学习资源**:学习JavaScript可以参考MDN Web...