一个词答案:异步性。
前言
这个话题在堆栈溢出中至少迭代了几千次。因此,首先,我想指出一些非常有用的资源:
@felix kling的答案:异步电话的响应?” 。请参阅他的出色答案,解释同步和异步流以及“重组代码”部分。
@Benjamin Gruenbaum还为解释同步线程中的异步性做出了很多努力。@matt Esch对“从fs.readfile获取数据”的答案也以一种简单的方式解释了异步性。
手头问题的答案
让我们首先追踪共同行为。在所有示例中,outerscopevar
在函数内进行了修改。该功能显然不会立即执行;它是作为参数分配或通过的。这就是我们所说的 回调 。
现在的问题是,该回调是什么时候打来的?
这取决于情况。让我们尝试再次追踪一些常见的行为:
img.onload
可以在将来的某个时候称为,何时(以及如果)已成功加载图像。settimeout
可以在将来的某个时候称为 过期,并且未通过clear> clear> clear> cleartimeout
取消超时。注意:即使使用0
作为延迟,所有浏览器也具有最小超时延迟帽(在HTML5规格中指定为4ms)。- jQuery
$。POST
的回调可以在将来的某个时候称为,何时(以及IF)AJAX请求已成功完成。 - Node.js的
fs.ReadFile
在将来的某个时候可以称为 成功读取文件或丢弃错误。
在所有情况下,我们都有一个回调,可以在以后的某个时候运行。我们将这种“将来的某个时候”称为异步流。
异步执行将从同步流中推出。也就是说,在同步代码堆栈执行时,异步代码将永远不会执行。这就是JavaScript被单线读取的含义。
更具体地说,当JS引擎闲置时 - 不执行(a)同步代码的堆栈 - 它将对可能触发异步回调的事件进行轮询(例如,过期的超时,接收到网络响应)并又一次地执行它们。这被认为是事件loop 。
也就是说,手绘红色形状中突出显示的异步代码只有在其各自的代码块中的所有剩余同步代码执行后才能执行:
简而言之,回调函数是同步创建但异步执行的。您不能依靠执行异步函数,直到您知道它已被执行,以及如何做到这一点?
真的很简单。取决于异步函数执行的逻辑应从此异步函数内部启动/调用。例如,在回调函数中移动警报
s和console.log
s将输出预期的结果,因为结果在此点可用。
通常,实现自己的回调逻辑,
您需要通过异步功能的结果做更多的事情,或者根据调用异步功能的位置,而将结果做不同的事情。让我们解决一个更复杂的示例:
var outerScopeVar;
helloCatAsync();
alert(outerScopeVar);
function helloCatAsync() {
setTimeout(function() {
outerScopeVar = 'Nya';
}, Math.random() * 2000);
}
注意:我正在使用settimeout
随机延迟作为通用异步函数;同一示例适用于Ajax,ReadFile
,onload
和任何其他异步流。
这个示例显然与其他示例相同的问题;直到异步函数执行之前,它才等待。
让我们通过实现自己的回调系统来解决它。首先,我们摆脱了那个丑陋的outerscopevar
,在这种情况下是完全无用的。然后,我们添加一个接受函数参数的参数,即我们的回调。当异步操作完成时,我们将调用此回调,通过结果。实现(请按顺序阅读评论):
// 1. Call helloCatAsync passing a callback function,
// which will be called receiving the result from the async operation
helloCatAsync(function(result) {
// 5. Received the result from the async function,
// now do whatever you want with it:
alert(result);
});
// 2. The "callback" parameter is a reference to the function which
// was passed as an argument from the helloCatAsync call
function helloCatAsync(callback) {
// 3. Start async operation:
setTimeout(function() {
// 4. Finished async operation,
// call the callback, passing the result as an argument
callback('Nya');
}, Math.random() * 2000);
}
上述示例的代码段:
// 1. Call helloCatAsync passing a callback function,
// which will be called receiving the result from the async operation
console.log("1. function called...")
helloCatAsync(function(result) {
// 5. Received the result from the async function,
// now do whatever you want with it:
console.log("5. result is: ", result);
});
// 2. The "callback" parameter is a reference to the function which
// was passed as an argument from the helloCatAsync call
function helloCatAsync(callback) {
console.log("2. callback here is the function passed as argument above...")
// 3. Start async operation:
setTimeout(function() {
console.log("3. start async operation...")
console.log("4. finished async operation, calling the callback, passing the result...")
// 4. Finished async operation,
// call the callback passing the result as argument
callback('Nya');
}, Math.random() * 2000);
}
在实际用例中,大多数情况下,DOM API和大多数库已经提供了回调功能(在此示例示例中Hellocatasync
实现)。您只需要传递回调函数,并了解它将从同步流中执行并重组代码以适应它。
您还会注意到,由于异步性质,不可能返回
从异步流回到定义回调的同步流中的值,因为异步回调是在同步之后执行的,代码已经完成执行。
您必须使用回调模式或...承诺,而不是返回
从异步回调中获得值。
承诺
虽然有多种方法可以保持“ noreferrer”> callback地狱与Vanilla JS一起在BAY中,承诺正在越来越受欢迎,目前正在标准化在ES6中(请参见 promise -promise -promise -mdn )。
承诺(又名期货)提供了对异步代码的更线性,因此令人愉悦的阅读,但是解释它们的整个功能不超出此问题的范围。取而代之的是,我将为有兴趣的人留下这些优质的资源:
性的更多阅读材料
- 有关JavaScript异步 >使用香草JS示例和node.js代码很好地说明异步代码和回调。
注意:我将这个答案标记为社区Wiki。因此,至少有100个声誉的人都可以编辑和改进它!如果您愿意,请随时提高此答案或提交全新的答案。
我想将这个问题变成一个与Ajax无关的异步问题的规范主题(有因此,从Ajax的电话中?
设置mapred.max.split.size = 2560000000;
增加单个地图处理的文件的大小,从而减少地图的数量
您的注册标题菜单带有标头键,并试图通过Top-Menu的钥匙将其获取,这是不可能的。您必须使用标头键键添加并获取标头菜单。我们已经更新了代码。您可以使用此代码。
<?php
wp_nav_menu( array(
'theme_location' => 'header-menu',
'container' => 'ul',
'menu_class'=> 'd-flex main-menu'
) );
?>
不确定这是否是修复的,但是我通过为ComboBox设置图标大小来解决它。我认为出了问题是,无论添加项目时图标的大小如何,可能都有一些默认的大小。我的图标尺寸为50x15,因此我添加了以下几行:
QSize size(50, 15);
ui.comboBox->setIconSize(size);
现在它正确完成并提供了正确的视图。
运行命令:
pip install jupyter
它对我有用。
我不习惯在PHP中进行编码的方式,但是对我来说,您的功能名称索引是您无法获得所需的原因。尝试将返回$ data
将其添加到您的代码中,这样看起来像这样:
public function index(){
$posts = $this->blogModel->getPosts();
$data = [
'posts' => $posts
];
$this->view('pages/blog', $data);
return $data;
}
尝试一下
_getImage(BuildContext context) async {
var picture = await ImagePicker().pickImage(source: ImageSource.gallery);
setState(() {
imageFile = File(picture!.path);
dirPath = picture.path;
print('path');
print(dirPath);
});
}
尝试此操作时,
df.drop('Unnamed: 0', axis = 1, inplace = True)
请始终使用Inplace = true当您更改数据框架中的某些内容或如果您不更改源dataframe,则尝试将其存储在不同的数据框架中,
new_df = df.drop('Unnamed: 0', axis = 1)
如果您只想知道拦截器是否正在返回正确的响应,则可以创建一个正在限制拦截器的类,并为handlemyException
提供公共包装方法。然后,您实例化了新课程,请致电包装器并断言返回的响应。
我不得不将所有应用都位于PythonPath环境变量的文件夹附加到这样的文件夹:pythonpath =“ $ {pythonpath}:/project_name/project_name”
cstring
包含lpctstr
的隐式转换操作员。它是为此精确使用而设计的。
这是您传递const
字符串的事实,无法修改使其安全。
我可能没有一种更好的方式。但是,我们可以通过
假设您有一个屏幕b
,您想向后滑动以转到屏幕home
,然后将params传递给home
from b
在该滑动动作上。然后,您可以如下实现这一目标。
function B({navigation}) {
React.useEffect(() => navigation.addListener('beforeRemove', (e) => {
// the navigation.navigate will fire beforeRemove which causes an infinite loop. we guard this here
if (e.data.action.type === "NAVIGATE") {
return
}
// Prevent default behavior of leaving the screen
e.preventDefault();
// navigate manually
navigation.navigate({
name: 'Home',
params: { post: postText },
merge: true,
});
}), [navigation]);
return ( ... )
}
编辑: navigation.navigate
很明显,beforeRemove
事件再次引起无限循环。我们可以如上图所示。
使用您正在查看的指定列分组的CTE和ROW_NUMBER可以干净地删除重复值,因为ROW_NUMBER逐步计数,并通过汇总的分区的重复值进行了重复计数。当订购时发现新的分组时,它将ROW_NUMBER重置为1,从下一个不同分组值的记录开始。
WITH CTE AS (
SELECT *,
ROW_NUMBER() OVER (PARTITION BY col1 ORDER BY col1) AS RN
FROM #temp
)
DELETE FROM CTE WHERE RN<>1
根据 [python.docs]:class ctypes.pypes.pydll(name,mode = default = default_mode = default_mode = default_mode = default_mode = default_mode = default_mode = default_mode = default_mode = default_mode = default_mode ,hander = none)(强调是我的):
因此,您应该用 pydll ( pydll )替换 cdll ( cdll )。
我加强了您的示例。
dll00.c :
code00.py :
输出:
According to [Python.Docs]: class ctypes.PyDLL(name, mode=DEFAULT_MODE, handle=None) (emphasis is mine):
So, you should replace cdll (CDLL) by pydll (PyDLL).
I enhanced your example a bit.
dll00.c:
code00.py:
Output:
python在c dll中