Hứa hẹn, chuyển các tham số bổ sung vào chuỗi


100

Một lời hứa, chẳng hạn như:

var P = new Promise(function (resolve, reject) {
  var a = 5;
  if (a) {
    setTimeout(function(){
      resolve(a);
    }, 3000);
  } else {
    reject(a);
  }
});

Sau khi chúng tôi gọi, sau đó phương thức trên lời hứa:

P.then(doWork('text'));

Hàm doWork trông như thế này:

function doWork(data) {
  return function(text) {
    // sample function to console log
    consoleToLog(data);
    consoleToLog(b);
  }
}

Làm cách nào để tránh trả về một hàm bên trong trong doWork, để có quyền truy cập vào dữ liệu từ các tham số văn bản và lời hứa? Có thủ thuật nào để tránh nội hàm không?


1
Tại sao có người cố tình từ bỏ cà ri ? Để sử dụng bindphương pháp ghê tởm ? - mà cũng cực kỳ chậm.

@ftor Tôi không hiểu bạn, bạn có thể vui lòng cung cấp một số mã để làm rõ?
Roland

Câu trả lời:


86

Bạn có thể sử dụng Function.prototype.bindđể tạo một hàm mới với giá trị được truyền cho đối số đầu tiên của nó, như thế này

P.then(doWork.bind(null, 'text'))

và bạn có thể thay đổi doWorkthành,

function doWork(text, data) {
  consoleToLog(data);
}

Bây giờ, textsẽ thực sự 'text'ở trong doWorkdatasẽ là giá trị được giải quyết bởi Lời hứa.

Lưu ý: Hãy đảm bảo rằng bạn đính kèm một trình xử lý từ chối vào chuỗi lời hứa của mình.


Chương trình làm việc: Bản sao trực tiếp trên Babel's REPL

function doWork(text, data) {
  console.log(text + data + text);
}

new Promise(function (resolve, reject) {
    var a = 5;
    if (a) {
      setTimeout(function () {
        resolve(a);
      }, 3000);
    } else {
      reject(a);
    }
  })
  .then(doWork.bind(null, 'text'))
  .catch(console.error);

cảm ơn, giúp, trước đó tôi cố gắng doWork.call (, 'text' này), nhưng dữ liệu đã được thay thế bằng 'text'
user3110667

2
callgọi một hàm tại chỗ, bindtạo một hàm mới, tuy nhiên, cả hai đều chấp nhận ngữ cảnh thực thi làm đối số đầu tiên của chúng.
sdgluck

103

Có lẽ câu trả lời đơn giản nhất là:

P.then(function(data) { return doWork('text', data); });

Hoặc, vì nó được gắn thẻ ecmascript-6, sử dụng các hàm mũi tên:

P.then(data => doWork('text', data));

Tôi thấy điều này dễ đọc nhất và không quá nhiều để viết.


5

Dùng cà ri.

var P = new Promise(function (resolve, reject) {
    var a = 5;
    if (a) {
        setTimeout(function(){
            resolve(a);
        }, 3000);
    } else {
        reject(a);
    }
});

var curriedDoWork = function(text) {
    return function(data) {
        console.log(data + text);
    }
};

P.then(curriedDoWork('text'))
.catch(
    //some error handling
);

b cẩn thận với điều này, nếu bạn tạo curriedDoWorkthành một lời hứa bằng cách thực hiện return new Promise()trên dòng đầu tiên của chức năng này, lời hứa được thực hiện ngay sau khi bạn gọi curriedDoWork()(như bạn làm trong..then(curriedDoWork('text'))
Ngọn lửa

@Flame: câu trả lời ngắn gọn, để thuận tiện cho bạn, bạn có thể gói lời hứa thành một hàm, nếu bạn muốn làm như vậy.
germain

@yks, bạn có thể đã chỉ ra cú pháp này khá thú vị const curriedWork = text => data => console.log (data + text)
germain

1
@germain à vâng, tôi đã từng thấy biểu mẫu này rồi, phải thích lập trình chức năng. Tuy nhiên, tôi gặp phải lỗi các chức năng mũi tên trong một số trình duyệt, vì vậy tôi có xu hướng tránh nó ngay bây giờ.
yks

@yks, chỉ có Internet Explorer không hỗ trợ nó và sẽ không bao giờ, vì Edge, lần xây dựng cuối cùng của Internet Explorer là ngày 9 tháng 12 năm 2015. Hãy tiếp tục ~
germain

0

Lodash cung cấp một giải pháp thay thế tốt cho điều chính xác này.

 P.then(_.bind(doWork, 'myArgString', _));

 //Say the promise was fulfilled with the string 'promiseResults'

 function doWork(text, data) {
     console.log(text + " foo " + data);
     //myArgString foo promiseResults
 }

Hoặc, nếu bạn muốn hàm thành công của mình chỉ có một tham số (kết quả lời hứa đã thực hiện), bạn có thể sử dụng nó theo cách này:

P.then(_.bind(doWork, {text: 'myArgString'}));

function doWork(data) {
    console.log(data + " foo " + this.text);
    //promiseResults foo myArgString
}

Điều này sẽ gắn text: 'myArgString'với thisngữ cảnh bên trong hàm.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.