【问题标题】:Mixing setTimeout with the callback functions - problem with returning values before the setTimeout ends将 setTimeout 与回调函数混合 - 在 setTimeout 结束之前返回值的问题
【发布时间】:2021-08-15 13:45:58
【问题描述】:

根据我昨天问的:Taking a value from Promise and returning it instead of console.log

我仍然有一个问题,因为当我尝试打开函数列表时,return results 甚至在它进入函数之前就发生了。我不能使用async/await,所以这就是我在这个练习中挣扎的原因。

有什么办法:

  1. 如果我 console.log(fun1(1000,callback)) 它不会返回任何东西(未定义),但我希望它返回值 res,但不是 console.logging 它,只是为了让回调返回它。
  2. 想法是将results 接受的那些结果放入pred,例如大于 5。
  3. 我知道问题可能出在 setTimeout 上,但正如我昨天发布的帖子中所述 - 我无法使用 async/await 来解决该问题。

我的代码:

function fun1(value,cb) {
    if ((value * 100) > 400)  {
        setTimeout(() => cb(null, value*100), 1000)
    }
    else {
       setTimeout(() => cb(new Error("error")), 1000)
    }
}
function fun2(value,cb) {
    if ((value * 20) > 50)  {
        setTimeout(() => cb(null, value*20), 2000)
    }
    else {
        setTimeout(() => cb(new Error("error")), 2000)
    }
}

function fun3(value,cb) {
    if ((value -30 ) > 0)  {
        setTimeout(() => cb(null, value-30), 3000)
    }
    else {
        setTimeout(() => cb(new Error("error")), 3000)
    }
}
function callback(err, res) {
    if (err) {
        console.log(err)
    }
    else {
        console.log(res)
        return res
    }


}
console.log(fun1(1000,callback))

const together = (funcs, pred) => (n) => {
    let results = []
    funcs.reduce((prev,curr) => {
        if (curr(n,callback) > pred) {
            results.push(curr(n,callback))
        }

    }, 0)
    return results
};

console.log(together([fun1,fun2,fun3], 5)(10))

【问题讨论】:

  • 我有一个问题,如果我删除那些超时,它仍然是异步函数吗?
  • 我的问题怎么样 - 如果我删除这些超时,它仍然是异步函数吗?很多次我都无法真正理解异步的含义。
  • 你问过setTimeout吗?setTimeout就像一个定时器,它稍后执行一个单元(回调),
  • 我的意思是 - 如果我删除 setTimeout,只留下 return cb(....),它是否仍然是 (fun1) 异步函数?
  • 不!为什么会这样?

标签: javascript node.js asynchronous callback


【解决方案1】:

过去人们因为回调而不敢写异步代码,我也是,所以我会用promise,

因此您需要从您的函数中返回一个Promise 对象,例如:

function fun1(value) {
    return new Promise((res, rej) => {
        if ((value * 100) > 400)
            setTimeout(() => res(value * 100), 1000)
        else
            setTimeout(() => rej(new Error("error")), 1000)
    });
}

我没有扭曲 Promise 对象,而是采用了不同的方法,我编写了一个实用函数 (callFuture),它调用 cl 并为我们返回一个 Promise 对象。

function callFuture(fn, value, cl) {
    return new Promise((res, rej) => {
        fn(value, (...v) => {
            let result = cl(...v);
            if (result instanceof Error)
                rej(result)
            else
                res(result)
        })
    });
}

function fun1(value, cb) {
    if ((value * 100) > 400)
        setTimeout(() => cb(null, value * 100), 1000)
    else
        setTimeout(() => cb(new Error("error")), 1000)
}
function fun2(value, cb) {
    if ((value * 20) > 50)
        setTimeout(() => cb(null, value * 20), 2000)
    else
        setTimeout(() => cb(new Error("error")), 2000)
}

function fun3(value, cb) {
    if ((value - 30) > 0)
        setTimeout(() => cb(null, value - 30), 3000)
    else
        setTimeout(() => cb(new Error("error")), 3000)
}

function callback(err, res) {
    return err ? err : res
}

callFuture(fun1, 100, callback)
    .then(console.log)
    .catch(console.log)

async function together(funcs, pred, n) {
    let results = [];
    for (const fn of funcs) {
        try {
            let v = await callFuture(fn, n, callback);
            if (v > pred)
                results.push(v);
        } catch (error) {
            console.log(`error`)
        }
    }
    return results;
}

together([fun1, fun2, fun3], 5, 10).then(console.log)

你可以认为await callFuture(fn, n, callback) 是同步的(这不是真的),不需要做任何事情来处理异步的东西,它会返回结果或抛出错误(很像同步函数),任何你可以处理try/catch 的错误就像你在同步函数中所做的那样......

【讨论】:

  • 非常感谢!你能告诉我(...v) 是什么意思吗?
  • 它的 es6 rest 运算符,它将所有 arg 包装为数组,例如 v[err, res]
【解决方案2】:

使用回调函数时有效

您的示例包括超时后的回调

 function fun1(value, calculate, callback) {
  if (value * 100 > 400) {
     setTimeout(() => {
      let result = calculate(null, value * 100);
      callback(result)
    }, 1000);
  } else {
     setTimeout(() => cb(new Error("error")), 1000);
  }
}

function calculate(err, res) {
  if (err) {
    console.log(err);
  } else {
    console.log(res);
    return res;
  }
}

fun1(1000, calculate, function(result) {
  console.log(`this is the result in the callback after timeout ${result}`)
});

【讨论】:

  • 不,它不起作用,因为它仍然没有返回任何内容,它会通过控制台记录它。你什么都没改变/跨度>
  • 好的,我明白了。所以我编辑了代码以在超时完成后添加一个回调函数。因此,当超时完成时,将使用计算中的值触发回调函数。那是你的旧 cb 函数
猜你喜欢
  • 2022-01-03
  • 2023-01-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-18
  • 1970-01-01
  • 2023-03-22
  • 1970-01-01
相关资源
最近更新 更多