我想我终于在大多数情况下都围绕着javascript/ES6 Promises.这并不容易!但是有些东西让我对这个设计感到困惑.
为什么Promise构造函数会进行回调?鉴于立即调用回调,调用者不能只执行该代码,从而避免一个不必要的心灵弯曲"不要打电话给我,我会打电话给你"?
以下是我所认为的Promise使用的原型示例,复制自Jake Archibald的Javascript Promises教程http://www.html5rocks.com/en/tutorials/es6/promises/#toc-promisifying-xmlhttprequest,并删除了注释.
它是XMLHttpRequest GET请求的基于Promise的包装器:
function get(url) {
return new Promise(function(resolve, reject) {
var req = new XMLHttpRequest();
req.open('GET', url);
req.onload = function() {
if (req.status == 200) {
resolve(req.response);
}
else {
reject(Error(req.statusText));
}
};
req.onerror = function() {
reject(Error("Network Error"));
};
req.send();
});
}
Run Code Online (Sandbox Code Playgroud)
对我来说,上面的代码将更容易理解,如果它被重写如下,使用我正在想象的一种非常不同的承诺,具有无参数构造函数和解析/拒绝方法:
function get(url) {
var promise = new MyEasierToUnderstandPromise();
var req = new XMLHttpRequest();
req.open('GET', url);
req.onload = function() {
if (req.status == 200) {
promise.resolve(req.response);
}
else { …Run Code Online (Sandbox Code Playgroud) 我的问题是" javascript中是否可以阻止失效的侦听器问题?" 但显然"问题"这个词会导致问题.
维基百科页面说,失败的监听器问题可以通过持有对观察者的弱引用的主题来解决.我之前在Java中已经实现了它并且它运行良好,我认为我将在Javascript中实现它,但现在我不知道如何.javascript甚至有弱引用吗?我看到有WeakSet和WeakMap具有在其名称中的"弱",但他们似乎并没有被这个有帮助,据我所看到的.
这是一个jsfiddle,显示了问题的典型案例.
html:
<div id="theCurrentValueDiv">current value: false</div>
<button id="thePlusButton">+</button>
Run Code Online (Sandbox Code Playgroud)
javascript:
'use strict';
console.log("starting");
let createListenableValue = function(initialValue) {
let value = initialValue;
let listeners = [];
return {
// Get the current value.
get: function() {
return value;
},
// Set the value to newValue, and call listener()
// for each listener that has been added using addListener().
set: function(newValue) {
value = newValue;
for (let listener …Run Code Online (Sandbox Code Playgroud) javascript dom garbage-collection weak-references observer-pattern
如果我理解正确的话,这里是一些在 1.5 下非法的示例 java 代码(因为@Override在 java 1.6 之前不能用于重写接口方法):
public class A {
public static interface MyInterface {
public void myInterfaceMethod();
}
public static class MyClass implements MyInterface {
@Override public void myInterfaceMethod() {}
}
}
Run Code Online (Sandbox Code Playgroud)
我想在我的源代码中找到所有此类 1.5 不兼容性,因此我在我的 ubuntu Linux 机器上安装了一个支持 java1.5 的编译器:
sudo apt install openjdk-8-jdk
JAVAROOT=/usr/lib/jvm/java-1.8.0-openjdk-amd64
${JAVAROOT}/bin/javac -version
# javac 1.8.0_232
Run Code Online (Sandbox Code Playgroud)
并编译了上面的java源代码:
${JAVAROOT}/bin/javac -source 1.5 -Xlint:all -Xlint:-options A.java
Run Code Online (Sandbox Code Playgroud)
我预计上面的java代码会被拒绝。但尽管在 1.5 下存在非法行为,但它显然编译成功了。
这是怎么回事?我是否误解了 1.5 规则@Override?或者我误解了-source 1.5应该做什么?
FWIW,我注意到这-source 1.4确实给出了预期的错误:
${JAVAROOT}/bin/javac -source …Run Code Online (Sandbox Code Playgroud) C++11 引入了线程安全的局部静态初始化,又名“神奇静态”:局部静态变量初始化在 C++11 中是线程安全的吗?
规范特别指出:
如果在初始化变量时控制同时进入声明,则并发执行应等待初始化完成。
所以这里有一个隐式的互斥锁。这非常有趣,而且似乎是一种异常现象——也就是说,我不知道 C++ 中内置了任何其他隐式互斥体(即不使用 std::mutex 之类的互斥体语义)。还有其他的吗,或者这在规范中是独一无二的?
我也很好奇是否可以利用 magic static 的隐式互斥体(或其他隐式互斥体,如果有的话)来实现其他同步原语。例如,我发现它们可以用来实现 std::call_once,因为:
std::call_once(onceflag, some_function);
Run Code Online (Sandbox Code Playgroud)
可以表示为:
static int dummy = (some_function(), 0);
Run Code Online (Sandbox Code Playgroud)
但请注意,魔术静态版本比 std::call_once 受到更多限制,因为使用 std::call_once 您可以重新初始化一次标志,因此每次程序执行多次使用该代码,而使用魔术静态,您实际上只能得到每次程序执行时使用一次。
这是我能想到的唯一一种不太明显的魔法静力学用途。
是否可以使用 magic static 的隐式互斥体来实现其他同步原语,例如通用 std::mutex 或其他有用的东西?
是否可以编写一个函数move_and_clear,以便对于任何STL容器:
do_something_with(move_and_clear(container));
Run Code Online (Sandbox Code Playgroud)
相当于:
do_something_with(std::move(container));
container.clear();
Run Code Online (Sandbox Code Playgroud)
?
这是我的第一次尝试,但是没有用.我认为我的类型是正确的(虽然它的生产版本可能会在一些std :: remove_reference中出现),并且它成功编译,但它失败或崩溃,因为在超出范围后访问临时.
template<class T>
T &&move_and_clear(T &t)
{
T scratch;
std::swap(scratch, t);
return std::move(scratch);
}
Run Code Online (Sandbox Code Playgroud)
这是我的第二次尝试.这实际上有效,但它是一个预处理器宏,因此是邪恶的:
template<class T>
T &&move_and_clear_helper(T &t, T &&scratch)
{
std::swap(scratch, t);
return std::move(scratch);
}
#define move_and_clear(t) move_and_clear_helper(t, decltype(t)())
Run Code Online (Sandbox Code Playgroud)
我的第三次尝试是另一个也可以工作的宏,这次是使用lambda而不是命名的辅助函数.所以它比以前的宏更加独立,但可能不太可读,当然它仍然是邪恶的,因为它是一个宏:
#define move_and_clear(t) \
[](decltype(t) &tparam, decltype(t) &&scratch){ \
std::swap(scratch, tparam); \
return std::move(scratch); \
}(t, decltype(t)())
Run Code Online (Sandbox Code Playgroud)
这是一个包含我三次尝试的可编辑程序:
/*
g++ --std=c++11 -W -Wall -g move_and_clear.cc -o move_and_clear1 -DWHICH=1
g++ --std=c++11 -W -Wall -g move_and_clear.cc -o move_and_clear2 -DWHICH=2
g++ --std=c++11 -W …Run Code Online (Sandbox Code Playgroud) If-None-Match请求头字段的行为在RFC7232 的第 3.2 节中指定。
我理解规范的这一部分,不需要解释。我不明白的是为什么标题被命名为“If-None-Match”。这对我来说和“Wherefore-Giraffe-Bathtub”一样有意义。
这个名字是否有理由,或者至少是一个体面的助记符,可以帮助我记住一周后的含义?
有时我运行kcachegrind,点击一会儿,点击关闭左侧面板的小'x'(哎呀!不知道如何取回它),点击更多,完全丢失,然后退出kcachegrind.
然后我再次在相同的输入文件上重新运行kcachegrind,希望重新开始,但相反,kcachegrind"帮助"记住我所处的破碎状态并让我回到那里,即完全丢失并且我有一个缺少的面板不知道怎么回来.
我该如何恢复?
我该如何回到起点?也就是说,默认布局,默认节点,默认其他一切.
我在ubuntu 14.04上使用KCachegrind版本0.7.4kde.
假设我想同时获取 10 个 url,并在收到响应时对其进行处理(其顺序可能与它们在原始列表中出现的顺序不同)。忽略拒绝的可能性,一种方法是简单地为每个 Promise 附加一个“then”回调,然后等待它们全部使用完成Promise.all()。
const fetch_promises = [
fetch("https://cors-demo.glitch.me/allow-cors"),
fetch("/"),
fetch("."),
fetch(""),
fetch("https://enable-cors.org"),
fetch("https://html5rocks-cors.s3-website-us-east-1.amazonaws.com/index.html"),
fetch("https://api.github.com"),
fetch("https://api.flickr.com/services/rest/"),
];
const processing_promises = [];
for (const fetch_promise of fetch_promises) {
processing_promises.push(fetch_promise.then(response => {
// Process response. In this example, that means just
// print it.
console.log("got a response: ",response);
}));
}
await Promise.all(processing_promises);
Run Code Online (Sandbox Code Playgroud)
切换到输出更清晰、更具确定性的示例:
const sleep = millis => new Promise(resolve=>setTimeout(resolve, millis));
const sleep_promises = [
sleep(3000).then(()=>"slept 3000"),
sleep(1000).then(()=>"slept 1000"),
sleep(5000).then(()=>"slept 5000"),
sleep(4000).then(()=>"slept 4000"),
sleep(2000).then(()=>"slept 2000"),
];
const processing_promises …Run Code Online (Sandbox Code Playgroud) javascript ×3
c++11 ×2
promise ×2
async-await ×1
c++ ×1
dom ×1
es6-promise ×1
fetch ×1
generator ×1
http ×1
http-headers ×1
java ×1
java-5 ×1
java-6 ×1
kcachegrind ×1