亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

將基于 Promise 的方法轉換為回調

將基于 Promise 的方法轉換為回調

慕碼人2483693 2022-10-21 10:12:45
我是 js 新手。我已經閱讀了許多關于異步性的先前堆棧溢出帖子,但仍然不明白下面的問題。我有以下代碼將圖像文件上傳到 S3 存儲桶。代碼需要實現的關鍵是讓父級中的 image1 變量將信息存儲在子函數中 s3.upload 調用的數據變量中。我使用以下承諾的代碼可以正常工作。我的理解是,同樣的事情可以只使用回調來完成,我一直試圖用回調重寫下面的代碼,只是作為一個學習練習,但它沒有奏效。我將如何更改此代碼以使用回調而不是承諾來做同樣的事情?父函數:try {      image1 = await uploadToAWSBucket(file);}catch (error) {      return next(error);}孩子:const uploadToAWSBucket = async (fileObject) => {  let randomFileName = shortid.generate();  const AWSUploadObject = {    Bucket: BUCKET_NAME,    Key: randomFileName,    Body: fileObject.buffer,    ContentType: fileObject.mimetype,  };  return new Promise((resolve, reject) => {    s3.upload(AWSUploadObject, (err, data) => {      if (err) {        return reject(err);      }      return resolve(data);    });  });   };
查看完整描述

4 回答

?
翻翻過去那場雪

TA貢獻2065條經驗 獲得超14個贊

首先,您需要為異步函數添加一個回調參數,刪除 async 關鍵字


const uploadToAWSBucket = (fileObject, callback) => {

接下來,您需要以回調方式處理 s3 響應,將 Promise 替換為回調使用。


s3.upload(AWSUploadObject, (err, data) => {

  if (err) {

    callback(err);

    return;

  }

  callback(null, data);

});

或者你甚至可以將其簡化為


s3.upload(AWSUploadObject, callback)

您還需要將您的使用更新為回調方式


uploadToAWSBucket(file, (error, image1) => {

  if (error) {

    next(error);

    return;

  }

  // your success code here

});

最終結果是


const uploadToAWSBucket = (fileObject, callback) => {

  let randomFileName = shortid.generate();

  const AWSUploadObject = {

    Bucket: BUCKET_NAME,

    Key: randomFileName,

    Body: fileObject.buffer,

    ContentType: fileObject.mimetype,

  };



  s3.upload(AWSUploadObject, callback);

};

而已。我希望這個解釋能幫助你理解如何使用回調。


查看完整回答
反對 回復 2022-10-21
?
12345678_0001

TA貢獻1802條經驗 獲得超5個贊

如果我的理解是正確的,你要image1catchblock之后使用。

在這種情況下,我想,您將使用image1. 可以按如下方式完成,其中一些片段來自此答案

const uploadToAWSBucket = (fileObject, callback) => { ... }; // described in the linked answer


uploadToAWSBucket(file, function callback(error, image1) {

  

  if(error) { return next(error); }


  someOtherFunction(image1, next); // "next" is passed as callback, with the assumption that nothing else needed to be called after that.  


});

如果你想用 的結果調用另外 2 個函數someOtherFunction,可以這樣做:


uploadToAWSBucket(file, function callback(error, image1) {

  

  if(error) { return next(error); }


  someOtherFunction(image1, function someOtherFunctionCb(error, someOtherFunctionResult) {


    if(error) { return next(error); }


    someOtherFunction2(someOtherFunctionResult, function someOtherFunction2Cb(error, someOtherFunction2Result) {


      if(error) { return next(error); }


      someOtherFunction3(someOtherFunction2Result, function someOtherFunction3Cb(error, someOtherFunction3Result) {


        if(error) { return next(error); }


        next(null, someOtherFunction3Result);


      });


    }); 


  }); 


});

基本上,如果您使用回調,則不能擁有局部全局變量。我將嘗試解釋一個問題的情況。



let image1 = null;


uploadToAWSBucket(file, function uploadToAWSBucketCallback(error, _image1) {

  

  if(error) { return next(error); }


  image1 = _image1;


});


someOtherFunction(image1, function someOtherFunctionCb(error, someOtherFunctionResult) {


  if(error) { return next(error); }


    ...


}); 


在上面的代碼片段中,someOtherFunction將在uploadToAWSBucketCallback執行之前調用。這意味著,image1沒有分配給_image1?,F在,您知道調用image1when的值是多少someOtherFunction。


第二個片段顯示了如何通過將后續調用嵌套在回調中來將一個異步函數的結果傳遞給另一個。這使許多人的代碼可讀性降低。有類似的庫async,這有助于使事情變得更容易和可讀。


第二個片段可以用async庫的waterfall函數重寫,如下所示:


async.waterfall([

    function uploadToAWSBucketStep(callback) {

        uploadToAWSBucket(file, callback);

    },

    function someOtherFunctionStep(image1, callback) {

        someOtherFunction(image1, callback);

    },

    function someOtherFunction2Step(someOtherFunctionResult, callback) {

        someOtherFunction2(someOtherFunctionResult, callback);

    },

    function someOtherFunction3Step(someOtherFunction2Result, callback) {

        someOtherFunction3(someOtherFunction2Result, callback);

    }

], function lastStep(error, someOtherFunction3Result) {

    if(error) { return next(error); };

    next(null, someOtherFunction3Result);

});


查看完整回答
反對 回復 2022-10-21
?
慕田峪9158850

TA貢獻1794條經驗 獲得超7個贊

在閱讀了每個人的回復后,我想出了以下我認為可行的方法,基本上是@Pavlo Zhukov 建議的。(請注意,函數名稱與我之前的帖子略有不同。)


來自父函數的代碼:


let image1;

uploadToAWSBucketCallbackStyle(file, (err, data) => {

  if (err) {

    return next(err);

  }

  image1 = data;

  // Do stuff with image1 here or make additional function

  // calls using image1.

});



子函數:


const uploadToAWSBucketCallbackStyle = (fileObject, callback) => {

  let randomFileName = shortid.generate();

  const AWSUploadObject = {

    Bucket: BUCKET_NAME,

    Key: randomFileName,

    Body: fileObject.buffer,

    ContentType: fileObject.mimetype,

  };


  s3.upload(AWSUploadObject, callback);

}


查看完整回答
反對 回復 2022-10-21
?
烙印99

TA貢獻1829條經驗 獲得超13個贊

Promisifcation 基于回調的函數是很好理解和有據可查的。

我從未見過關于“去承諾”的討論,但這很簡單。

從您開始uploadToAWSBucket()并假設您希望您的回調是“nodeback”樣式(簽名(err, data)),那么您可以編寫:

const uploadToAWSBucketNodeback = (fileObject, nodeback) => {

    uploadToAWSBucket(fileObject) // call the promise-returning "async" version.

    .then(data => { // success path

        nodeback(null, data);

    })

    .catch(nodeback); // error path

};

或者你可以寫一個通用的去承諾...


const depromisify = (asyncFunction) => {

    return function(...params) {

        let nodeback = params.pop(); // strip nodeback off the end of params

        asyncFunction(...params)

        .then(data => { // success path

            nodeback(null, data);

        })

        .catch(nodeback); // error path

    }

};

... 然后


const uploadToAWSBucketNodeback = depromisify(uploadToAWSBucket);

任何一種方法都允許您編寫:


uploadToAWSBucketNodeback(fileObject, function(err, data)) {

    if(err) {

        // handle error

    } else {

        // handle data

    }

}

筆記

  • 我們只需要知道原始的 asyncFunction 是 thenable/catchable 即可。

  • 原始的 asyncFunction 對 depromisified 函數完全不透明。

  • 我們不需要了解原始 asyncFunction 的內部工作原理。因此,AWSUploadObject不需要復制的組成......它仍然由uploadToAWSBucket().


查看完整回答
反對 回復 2022-10-21
  • 4 回答
  • 0 關注
  • 158 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號