Heim > Fragen und Antworten > Hauptteil
Zum Beispiel gibt es drei Funktionen a, b und c, die alle Synchronisierungsvorgänge ausführen. Zur Vereinfachung habe ich die Synchronisierungsvorgänge vereinfacht
function c(m) {
m = m + 1;
return m;
}
function b(m) {
m = m + 1;
return c(m);
}
function a(){
let m = 0;
return b(m);
}
Die Ausgabe der Ausführung von a() ist 2Aber wenn die c-Funktion beispielsweise keine synchrone Funktion, sondern eine asynchrone Operation ausführt
function c(m) {
setTimeout(function () {
m = m + 1;
}, 1000)
return m;
}
Wenn Sie beim Ausführen von a() korrekt 2 ausgeben möchten, müssen Sie c durch Promise oder Async kapseln, Ähnlich wie
function promiseC(m) {
return new Promise((resolve, reject) => {
setTimeout(function () {
m = m + 1;
resolve(m);
}, 1000)
}
}
async function c(m) {
m = await promiseC(m);
return m;
}
Da c zu einer asynchronen Funktion wird, muss b c aufrufen, b muss auch in asynchron geändert werden und so weiter, a muss ebenfalls in asynchron geändert werden
async function b(m) {
m = m + 1;
return await c(m);
}
async function a(){
let m = 0;
return await b(m);
}
a().then(function(data) {
console.log(data)
}) Auf diese Weise können 2ausgegeben werden
Um 2 korrekt auszugeben, habe ich sowohl a als auch b geändert. Ich frage mich, ob es eine andere Möglichkeit gibt, die Änderung von a und b zu vermeiden und die korrekte Ausgabe zu erzielen.Da ich die asynchrone Situation nicht berücksichtigt habe, als ich zum ersten Mal mit dem Schreiben des Codes begonnen habe, sind Funktionen wie a und b in verschiedenen Dateien verteilt, und es gibt viele davon, damit c asynchrone Vorgänge ausführen kann Es ist zu schwierig, sie zu ändern. Ich weiß es nicht. Haben Sie andere gute Methoden?
Das obige Problem kann gelöst werden, indem das Versprechensobjekt in der Antwort unten direkt zurückgegeben wird, aber die tatsächliche Codestruktur ist eher so
function c(m) {
m = m + 1;
return m;
}
function b(m) {
m = m + 1;
let n = c(m)
n = n + 1
return n;
}
function a(){
let m = 0;
let k = b(m);
k = k + 1;
return k;
}
Wenn ich dieser Methode folge, muss ich die Rückgabemethoden von a und b ändern, damit a und b Versprechensobjekte zurückgeben können.
Für eine solche Struktur weiß ich nicht, ob es eine Möglichkeit gibt, ohne diese eine korrekte Ausgabe zu erzielen Ändern der Funktionen von a und b
阿神2017-07-03 11:43:44
很遗憾的告诉你,node这边是显式异步的,所以你把一个函数从同步改成异步,那么依赖它的函数也必须做更改,重构的时候确实是个头疼的事情,你还是忍着改改吧。
像fibjs这种不需要异步关键字的重构起来就很省心了,你改了c不需要改动a和b,因为隐式异步不需要你指示它。
PHP中文网2017-07-03 11:43:44
还是对Promise的理解不到位啊。这里没必要改动b()
和a()
的。
对于函数c
,只需要返回一个promise
对象,经过函数b
的时候,直接同步返回这个Promise对象,不需要改动函数b使其为异步函数,因为异步操作是在函数c
中,b
中只进行了同步操作。此时需要在函数a
中捕获这个Promise,所以代码可以改成这样
function promiseC(m) {
return new Promise((resolve, reject) => {
setTimeout(function () {
m = m + 1;
resolve(m);
}, 1000)
})
}
function c(m) {
m = promiseC(m);
return m;
}
function b(m) {
m = m + 1;
return c(m);
}
function a() {
let m = 0;
return b(m);
}
p.then(function(a){
console.log(a)
})
所以,这里函数a(),b()
如果不处理异步操作的返回值,那为何要把他改成Async函数呢。
滿天的星座2017-07-03 11:43:44
不得不说我盯着屏幕打了好些草稿, 最终还是失败了.
我想不出有什么方法能在 js 里阻塞当前函数但是又能及时执行 promise 的 resolve. 失败的思路如下
c_result=null
c=async (m)=>{return m+1}
c_sync = (m)=>{
let n=0
pc=c(m).then((m)=>{c_result=m})
while(c_result===null && n++<100){}
return c_result
}
b=(m)=>{return c_sync(m+1)}
a=()=>{return b(0)}
a()
它的问题在于, 虽然while(c_result===null && n++<100){}
阻塞了函数c_sync, 但是也阻止了.then
回调的执行. 由于单线程异步的机制, 当某一个回调触发的时候, 如果线程正忙, 这个回调是没法插队的, 从而导致循环执行过程中, c_result没办法被变量 m 赋值.也就没办法退出循环.
但是我觉得这个问题很有意思. 找到了一篇相关文章. 作者通过一个外部二进制库结局了局部阻塞的问题.
http://blog.csdn.net/xingqili...
我的理解是:
基于 js 引擎自身的事件循环, 我们不能阻塞某个块. 因为对于 js 代码而言引擎的事件循环是在底层. 但是对于外部的二进制模块而言. 其可以阻塞自身, 并保证 js 引擎的事件循环每一次都完全遍历事件队列----以保证自身阻塞期间在 js 引擎中新增的事件能被处理.
巴扎黑2017-07-03 11:43:44
让a()输出promise,确实可以解决我提到的问题
但是在真正修改代码的时候,我发现大部分代码的结构不是我上面问题这样的
而是下面新补充的结构
function c(m) {
m = m + 1;
return m;
}
function b(m) {
m = m + 1;
let n = c(m)
n = n + 1
return n;
}
function a(){
let m = 0;
let k = b(m);
k = k + 1;
return k;
}
世界只因有你2017-07-03 11:43:44
恕我直言,你没有对 node.js 的事件循环机制和 event 核心模块作深入的了解。
promise 和 aysnc/await 确实是如今处理异步流程控制的主流,但并不是说没有了它们就做不了了,这种简单的问题回溯到 event 方式处理即可。
const EventEmitter = require('events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('a', (m) => {
console.log('a -> b');
myEmitter.emit('b', m+1);
});
myEmitter.on('b', (m) => {
console.log('b -> c');
myEmitter.emit('c', m+1);
});
myEmitter.on('c', (m) => {
console.log('result', m);
});
myEmitter.emit('a', 0);