正确地将参数传递给setTimeout

时间:2017-11-15 00:41:04

标签: javascript node.js promise settimeout

我正在开发一个Node.js项目,我在使用Promise函数包装setTimeout函数时遇到问题。

我原来的Promise功能:

我想在调用setTimeout()时包装此函数,但在传递Promise对象时遇到问题。我需要Promise对象和setTimeout()函数中可用的数据对象,但当我将它们作为参数传递给setTimeout()时,我仍然会收到以下错误:

  

TypeError:无法读取属性'然后'未定义的

我的代码:

return Promise.props(data).then(function (data) {
    data.companies = data.order && data.order.companies;
    if (!data.companies) {
        data.companies = {};
        data.companies[data.company.id] = data.company;
    }

    if (data.order) {
        if (data.order.contactentry) {
            data.order.pointofcontact = data.order.contactentry + ' ' + phone(data.order.contactentryphone);
        } else if (data.order.borrowername) {
            data.order.pointofcontact = data.order.borrowername + ' ' + phone(data.order.borrowerphone);
        } else if (data.order.lockboxcode) {
            data.order.pointofcontact = 'Lockbox ' + data.order.lockboxcode
        }
    }

    if (data.part && data.order && data.part.vendor) {
        var oid = data.order && data.order.id;
        var vid = data.part && data.part.vendor && data.part.vendor.id;
        if (!oid || !vid) {
            var e = new Error('Could not assemble vendor accept url, order id or part vendor id are missing')
            log.error({
                error: e,
                data,
            }, e.message);
            throw e;
        }
    }

    return data;
});

当作为参数传入时,数据对象在函数内部可用,但Promise对象不可用。 如何正确传递Promise对象以使其在setTimeout()内可用?

2 个答案:

答案 0 :(得分:3)

你正在从内到外接近这个。如果要将非承诺异步代码(例如setTimeout)合并到基于承诺的代码中,则应该隔离包装的非承诺部分,而不是将其与其余的承诺代码混合得太深。

setTimeout的承诺包装:

function delay(ms) {
  return new Promise(function (resolve) {
    setTimeout(resolve, ms);
  });
}

然后你可以使用它:

return Promise.props(data)
    .then(function (result) {
      return delay(1000).return(result);
    });

由于您似乎在使用Bluebird,您还可以跳过所有setTimeout内容并使用内置的.delay方法:

return Promise.props(data).delay(1000);

请注意,上述任何一项都会将额外的 1秒延迟添加到解析data中所有承诺所需的时间。如果您的目标只是让最短总时间为1秒,那么您可以使用this question中的方法:

return Promise.delay(1000).return(Promise.props(data));

答案 1 :(得分:0)

我会忘记使用setTimeout的参数/返回值,只使用new Promise

在调用Promise.props之前延迟:

return new Promise(function (resolve) {
  window.setTimeout(function () {
    resolve(Promise.props(data));
  }, 1000);
});

或者,延迟Promise.props的结果:

return Promise.props(data).then(function (data) {
  return new Promise(function (resolve) {
    window.setTimeout(function () {
      resolve(data);
    }, 1000);
  });
});

编辑:如果你正在使用Bluebird,看起来它们内置了延迟运算符: