【问题标题】:Creating a Promise in Javascript在 Javascript 中创建 Promise
【发布时间】:2021-03-09 16:46:58
【问题描述】:

我希望这个函数 tagFindOrCreate 仅在第一个函数完成时执行:

func.tweetCreate(bmTweet, user)
    .then(function () {
            func.tagFindOrCreate(bmTweet, bmtTag, user)
    })

帮我为这个函数创建一个承诺:

tweetCreate: function (tweet, user) {
    Tweet.create(tweet, function (err, tweet) {
        user[0].tweets.push(tweet)
        user[0].save()
        console.log("Tweet saved.")
        return Promise.resolve()
    })
}

【问题讨论】:

  • 什么是Tweet?这是来自第三方库吗?
  • 不,这是我创建的猫鼬模型。
  • 如果你写了 Tweet.create 为什么不让它返回一个 Promise 而不是支持回调,而不是把它包装成一个呢?
  • @Jamiec 如果我这样做,函数会变得非常大。另外,我想重用 Tweet.create 而不是每次都创建标签。
  • @AnshAgarwal 零意义。要么支持回调,要么支持Pomises,两者都不需要

标签: javascript node.js promise frontend backend


【解决方案1】:

如下:

tweetCreate: function (tweet, user) {
    return new Promise(resolve => {
        Tweet.create(tweet, function (err, tweet) {
            user[0].tweets.push(tweet);
            user[0].save();
            console.log("Tweet saved.")
            resolve();
        })
    }
};

【讨论】:

    【解决方案2】:

    由于Tweet 是一个猫鼬模型,只要您不传递回调,它的create 方法就会返回一个promise。这意味着您可以将回调逻辑移动到发生承诺解决的地方。最简单的方法是使用an async function

    tweetCreate: async function (tweetContents, user) {
      const createdTweet = await Tweet.create(tweetContents);
      user[0].tweets.push(createdTweet);
      user[0].save();
      console.log('tweet saved');
    }
    

    关于错误处理的说明async 函数将已经返回一个承诺或可能引发错误(如果 Tweet.create 中有错误)。上面的代码将传播错误,因此请确保如果您使用async/await,则将调用代码包装在try/catch 或使用.catch 处理需要的错误.由您的应用程序的逻辑决定您是否需要在tweetCreate 本身中捕获错误,或者您是否可以将其传播到可以捕获和处理的应用程序代码级别,但请注意需要处理潜在的承诺错误。


    为了完整起见,您可以承诺Tweet.create。如今,库方法返回承诺很常见,因此很少需要手动承诺。如果您觉得需要承诺,请记住这一点……图书馆可能已经有一个机制。

    您可以简单地使用Promise 构造函数手动执行此操作。这需要一个回调,该回调接受一个 resolve 参数,您可以从另一个回调中调用该参数来解决承诺:

    return Promise(resolve => {
       Tweet.create(tweet, (error, createdTweet) {
         ...
         resolve();
       });
    });
    

    Node.js 也有一个内置的 promisify 函数,因此为此目的可能不需要使用 Promise 构造函数。你可以这样做:

    const createTweet = util.promisify(Tweet.create);
    const createdTweet = await createTweet(tweet);
    ...
    

    注意:以上只是一个例子。猫鼬模型没有必要这样做。

    【讨论】:

      【解决方案3】:

      您需要使用 Promise 构造函数创建一个 Promise,tweetCreate() 应该返回该 Promise。

      Tweet.create(...)的调用应该在内部执行器函数(传递给promise构造函数的函数)并且来自Tweet.create(...)的回调函数内部,您需要调用resolve() 函数来履行承诺。

      您需要将函数的实现更改为如下所示:

      tweetCreate: function (tweet, user) {
          return new Promise((resolve, reject) => {
              Tweet.create(tweet, function (err, tweet) {
                user[0].tweets.push(tweet);
                user[0].save();
                resolve();      //  <--- this will resolve the promise
              });
          });
      }
      

      调用resolve() 将履行导致调用then() 方法的回调函数的承诺。


      编辑

      您在评论中提到Tweet 是猫鼬模型;在这种情况下,您不需要明确地创建承诺。 Mongoose 提供了一个基于 Promise 的 API,用于在数据库中创建和保存文档,您应该使用它而不是自己创建 Promise。

      【讨论】:

      • 现在在大多数情况下,您应该不需要使用 Promise 构造函数。 util.promisify 可用于此目的,大多数库都有内置的承诺,包括猫鼬模型。
      • @ExplosionPills OP 没有在问题中提到猫鼬,但您的观点已得到适当注意。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-02
      • 1970-01-01
      相关资源
      最近更新 更多